From e0aaa08c49f5d4e8cf8af095cea97c3abe32781a Mon Sep 17 00:00:00 2001 From: proller Date: Mon, 29 Sep 2025 00:30:24 +0200 Subject: [PATCH 01/36] earth --- src/fm_map.cpp | 36 +++++++++++++++++++------------- src/fm_weather.h | 9 ++++++++ src/mapgen/earth/arnis-cpp | 2 +- src/mapgen/earth/arnis_adapter.h | 28 ++++++++++++------------- src/mapgen/mapgen.cpp | 11 ++++++++++ src/mapgen/mapgen.h | 10 ++++++--- src/mapgen/mapgen_earth.cpp | 31 ++++++++++++++++++++++++--- src/mapgen/mapgen_earth.h | 18 +++++++++++++--- src/mapgen/mg_biome.cpp | 4 ++-- src/mapgen/mg_biome.h | 7 ++++--- src/servermap.h | 14 ++++++------- 11 files changed, 117 insertions(+), 53 deletions(-) create mode 100644 src/fm_weather.h diff --git a/src/fm_map.cpp b/src/fm_map.cpp index 25778ba4e..b7d775377 100644 --- a/src/fm_map.cpp +++ b/src/fm_map.cpp @@ -47,7 +47,7 @@ thread_local v3bpos_t block_cache_p; } #endif -std::atomic_uint ServerMap::time_life {}; +std::atomic_uint ServerMap::time_life{}; // TODO: REMOVE THIS func and use Map::getBlock MapBlockPtr Map::getBlock(v3bpos_t p, bool trylock, bool nocache) @@ -77,7 +77,8 @@ MapBlockPtr Map::getBlock(v3bpos_t p, bool trylock, bool nocache) MapBlockPtr block; { - const auto lock = trylock ? m_blocks.try_lock_shared_rec() : m_blocks.lock_shared_rec(); + const auto lock = + trylock ? m_blocks.try_lock_shared_rec() : m_blocks.lock_shared_rec(); if (!lock->owns_lock()) return nullptr; const auto &n = m_blocks.find(p); @@ -238,7 +239,7 @@ MapNode Map::getNodeNoLock(v3POS p) //dont use } */ -s16 Map::getHeat(const v3pos_t &p, bool no_random) +s16 Map::getHeat(const v3bpos_t &p, bool no_random) { MapBlock *block = getBlockNoCreateNoEx(getNodeBlockPos(p)); if (block != NULL) { @@ -249,7 +250,7 @@ s16 Map::getHeat(const v3pos_t &p, bool no_random) return 0; } -s16 Map::getHumidity(const v3pos_t &p, bool no_random) +s16 Map::getHumidity(const v3bpos_t &p, bool no_random) { MapBlock *block = getBlockNoCreateNoEx(getNodeBlockPos(p)); if (block != NULL) { @@ -260,8 +261,8 @@ s16 Map::getHumidity(const v3pos_t &p, bool no_random) return 0; } -ServerMap::heat_t ServerMap::updateBlockHeat(ServerEnvironment *env, const v3pos_t &p, - MapBlock *block, unordered_map_v3pos *cache, bool block_add) +weather::heat_t ServerMap::updateBlockHeat(ServerEnvironment *env, const v3pos_t &p, + MapBlock *block, unordered_map_v3bpos *cache, bool block_add) { const auto bp = getNodeBlockPos(p); const auto gametime = env->getGameTime(); @@ -274,8 +275,10 @@ ServerMap::heat_t ServerMap::updateBlockHeat(ServerEnvironment *env, const v3pos if (cache && cache->contains(bp)) { return cache->at(bp); // + myrand_range(0, 1); } - auto value = m_emerge->biomemgr->calcBlockHeat(p, getSeed(), env->getTimeOfDayF(), - gametime * env->m_time_of_day_speed, env->m_use_weather); + auto value = + m_emerge->getFirstMapgen()->calcBlockHeat(p, getSeed(), env->getTimeOfDayF(), + gametime * env->m_time_of_day_speed, env->m_use_weather); + //auto value = m_emerge->biomemgr->calcBlockHeat(p, getSeed(), env->getTimeOfDayF(), gametime * env->m_time_of_day_speed, env->m_use_weather); if (!block) { block = getBlockNoCreateNoEx(bp); //, true); @@ -283,7 +286,7 @@ ServerMap::heat_t ServerMap::updateBlockHeat(ServerEnvironment *env, const v3pos { int8_t blocks_around = 0; - heat_t sum = 0; + weather::heat_t sum = 0; for (const auto &dir : g_6dirs) { if (auto nblock = getBlockNoCreateNoEx(bp + dir, true)) { sum += nblock->humidity; @@ -313,9 +316,9 @@ ServerMap::heat_t ServerMap::updateBlockHeat(ServerEnvironment *env, const v3pos return value; // + myrand_range(0, 1); } -ServerMap::humidity_t ServerMap::updateBlockHumidity(ServerEnvironment *env, +weather::humidity_t ServerMap::updateBlockHumidity(ServerEnvironment *env, const v3pos_t &p, MapBlock *block, - unordered_map_v3pos *cache, bool block_add) + unordered_map_v3bpos *cache, bool block_add) { const auto bp = getNodeBlockPos(p); const auto gametime = env->getGameTime(); @@ -328,8 +331,11 @@ ServerMap::humidity_t ServerMap::updateBlockHumidity(ServerEnvironment *env, if (cache && cache->count(bp)) { return cache->at(bp) + myrand_range(0, 1); } - auto value = m_emerge->biomemgr->calcBlockHumidity(p, getSeed(), env->getTimeOfDayF(), - gametime * env->m_time_of_day_speed, env->m_use_weather); + + auto value = + m_emerge->getFirstMapgen()->calcBlockHeat(p, getSeed(), env->getTimeOfDayF(), + gametime * env->m_time_of_day_speed, env->m_use_weather); + //auto value = m_emerge->biomemgr->calcBlockHumidity(p, getSeed(), env->getTimeOfDayF(),gametime * env->m_time_of_day_speed, env->m_use_weather); if (!block) { block = getBlockNoCreateNoEx(bp); //, true); @@ -337,7 +343,7 @@ ServerMap::humidity_t ServerMap::updateBlockHumidity(ServerEnvironment *env, { int8_t blocks_around = 0; - humidity_t sum = 0; + weather::humidity_t sum = 0; for (const auto &dir : g_6dirs) { if (auto nblock = getBlockNoCreateNoEx(bp + dir, true)) { sum += nblock->humidity; @@ -1640,7 +1646,7 @@ s32 ServerMap::save(ModifiedState save_level, float dedicated_server_step, bool //modprofiler.add(block->getModifiedReasonString(), 1); const auto lock = breakable ? block->try_lock_unique_rec() - : block->lock_unique_rec(); + : block->lock_unique_rec(); if (!lock->owns_lock()) continue; diff --git a/src/fm_weather.h b/src/fm_weather.h new file mode 100644 index 000000000..f3adba768 --- /dev/null +++ b/src/fm_weather.h @@ -0,0 +1,9 @@ +#pragma once + +#include + +namespace weather +{ +using humidity_t = int16_t; +using heat_t = int16_t; +} diff --git a/src/mapgen/earth/arnis-cpp b/src/mapgen/earth/arnis-cpp index 6633c9e3b..d807f189a 160000 --- a/src/mapgen/earth/arnis-cpp +++ b/src/mapgen/earth/arnis-cpp @@ -1 +1 @@ -Subproject commit 6633c9e3b57afa7e83a1901557bc5b297304e7ff +Subproject commit d807f189a0fe6d998436e1be31135f212c92e11c diff --git a/src/mapgen/earth/arnis_adapter.h b/src/mapgen/earth/arnis_adapter.h index d8332e638..8f1b09e32 100644 --- a/src/mapgen/earth/arnis_adapter.h +++ b/src/mapgen/earth/arnis_adapter.h @@ -260,6 +260,7 @@ struct Ground // Return ground level for a single XZ point int level(const XZPoint &pos) const { + ++mg->stat.level; const auto h = mg->get_height(pos.X, pos.Y); return h; } @@ -287,16 +288,8 @@ struct WorldEditor { // Implementation for adding a block to the world const auto yg = ground->level({x, z}); - const v3pos_t pos{ - static_cast(x), static_cast(yg + y), static_cast(z)}; - if (!mg || !mg->vm) { - DUMP("broken mg"); - return; - } - if (mg->vm->exists(pos)) { - mg->vm->setNode(pos, block); - } + return set_block_absolute(block, x, yg + y, z, replace_with, avoid); } void set_block(const Block &block, int x, int y, int z, @@ -343,6 +336,9 @@ struct WorldEditor } if (mg->vm->exists(pos)) { mg->vm->setNode(pos, block); + ++mg->stat.set; + } else { + ++mg->stat.miss; } } @@ -362,6 +358,8 @@ struct WorldEditor const v3pos_t pos{ static_cast(x), static_cast(y), static_cast(z)}; + ++mg->stat.check; + if (!mg->vm->exists(pos)) return false; @@ -372,9 +370,11 @@ struct WorldEditor //inline auto node_to_xz(const osmium::NodeRef &node) inline auto node_to_xz(const auto &node) { - const auto pos2 = mg->ll_to_pos({static_cast(node.y()) / - osmium::detail::coordinate_precision, - static_cast(node.x()) / osmium::detail::coordinate_precision}); + const auto pos2 = mg->ll_to_pos( + {static_cast(node.y()) / + static_cast(osmium::detail::coordinate_precision), + static_cast(node.x()) / + static_cast(osmium::detail::coordinate_precision)}); // TODO: scale y return std::make_pair(pos2.X, pos2.Y); } @@ -398,7 +398,6 @@ struct WorldEditor auto [min_x, max_x] = std::minmax(x1, x2); auto [min_y, max_y] = std::minmax(y1, y2); auto [min_z, max_z] = std::minmax(z1, z2); - for (std::int32_t x = min_x; x <= max_x; ++x) { for (std::int32_t y = min_y; y <= max_y; ++y) { for (std::int32_t z = min_z; z <= max_z; ++z) { @@ -407,6 +406,7 @@ struct WorldEditor } } } + ++mg->stat.fill; } void fill_blocks(const Block &block, std::int32_t x1, std::int32_t y1, @@ -444,13 +444,11 @@ struct WorldEditor } - using namespace world_editor; } #include "arnis-cpp/src/block_definitions.h" - namespace arnis { void init(MapgenEarth *mg); diff --git a/src/mapgen/mapgen.cpp b/src/mapgen/mapgen.cpp index d82e65e30..e6f818834 100644 --- a/src/mapgen/mapgen.cpp +++ b/src/mapgen/mapgen.cpp @@ -7,6 +7,7 @@ #include #include "irr_v3d.h" #include "mapgen.h" +#include "servermap.h" #include "voxel.h" #include "noise.h" #include "gamedef.h" @@ -1262,3 +1263,13 @@ const MapNode &Mapgen::visible_content(const v3pos_t &p, bool use_weather) : heat < 40 ? (humidity < 20 ? visible_surface_dry : visible_surface_green) : visible_surface_hot; } + +weather::heat_t Mapgen::calcBlockHeat(const v3pos_t &p, uint64_t seed, float timeofday, float totaltime, bool use_weather) +{ + return m_emerge->biomemgr->calcBlockHeat(p, seed, timeofday, totaltime, use_weather); +} + +weather::humidity_t Mapgen::calcBlockHumidity(const v3pos_t &p, uint64_t seed, float timeofday, float totaltime, bool use_weather) +{ + return m_emerge->biomemgr->calcBlockHumidity(p, seed, timeofday, totaltime, use_weather); +} diff --git a/src/mapgen/mapgen.h b/src/mapgen/mapgen.h index afa369fe7..0a5fba6c3 100644 --- a/src/mapgen/mapgen.h +++ b/src/mapgen/mapgen.h @@ -6,6 +6,7 @@ #pragma once +#include "fm_weather.h" #include "noise.h" #include "nodedef.h" #include "util/string.h" @@ -239,10 +240,10 @@ public: virtual int getGroundLevelAtPoint(v2s16 p) { return 0; } // freeminer: - ServerEnvironment *env = nullptr; + ServerEnvironment *env {}; s16 liquid_pressure = 0; - unordered_map_v3pos heat_cache; - unordered_map_v3pos humidity_cache; + unordered_map_v3bpos heat_cache; + unordered_map_v3bpos humidity_cache; MapNode visible_surface; MapNode visible_surface_green; @@ -257,6 +258,9 @@ public: virtual bool visible_water_level(const v3pos_t &p); virtual const MapNode &visible_content(const v3pos_t &p, bool use_weather); virtual bool surface_2d() { return true; }; + virtual weather::heat_t calcBlockHeat(const v3pos_t &p, uint64_t seed, float timeofday, float totaltime, bool use_weather); + virtual weather::humidity_t calcBlockHumidity(const v3pos_t &p, uint64_t seed, float timeofday, float totaltime, bool use_weather); + // === // getSpawnLevelAtPoint() is a function within each mapgen that returns a // suitable y co-ordinate for player spawn ('suitable' usually meaning diff --git a/src/mapgen/mapgen_earth.cpp b/src/mapgen/mapgen_earth.cpp index 8b7e537b7..3243e6748 100644 --- a/src/mapgen/mapgen_earth.cpp +++ b/src/mapgen/mapgen_earth.cpp @@ -23,6 +23,7 @@ along with Freeminer. If not, see . #include #include #include +#include #include #include #include @@ -256,6 +257,10 @@ ll MapgenEarth::pos_to_ll(const pos_t x, const pos_t z) return {89.9999, 0}; } } +ll MapgenEarth::pos_to_ll(const v3pos_t &p) +{ + return pos_to_ll(p.X, p.Z); +} v2pos_t MapgenEarth::ll_to_pos(const ll &l) { @@ -288,7 +293,7 @@ int MapgenEarth::generateTerrain() for (pos_t z = node_min.Z; z <= node_max.Z; z++) { for (pos_t x = node_min.X; x <= node_max.X; x++, index++) { - s16 heat = + auto heat = m_emerge->env->m_use_weather ? m_emerge->env->getServerMap().updateBlockHeat(m_emerge->env, v3pos_t(x, node_max.Y, z), nullptr, &heat_cache) @@ -375,8 +380,7 @@ void MapgenEarth::generateBuildings() const auto lon_dec = lon_start(tc.lon); static const auto timestamp = []() { - // const std::string ts = "202509040800"; - std::string ts = "latest"; + std::string ts = "latest"; g_settings->getNoEx("earth_movisda_timestamp", ts); return ts; }(); @@ -449,5 +453,26 @@ void MapgenEarth::generateBuildings() if (const auto &hdlr = maps_holder->osm_bbox.get(bbox)) { hdlr->apply(); } + + warningstream << "Buildings stat: " << node_min << " set=" << stat.set + << " miss=" << stat.miss << " level=" << stat.level + << " check=" << stat.check << " fill=" << stat.fill << "\n"; + stat = {}; + #endif } + +weather::heat_t MapgenEarth::calcBlockHeat(const v3pos_t &p, uint64_t seed, + float timeofday, float totaltime, bool use_weather) +{ + const auto ll = pos_to_ll(p); + const auto tile = osmium::geom::Tile(3, osmium::Location(ll.lon, ll.lat)); + return m_emerge->biomemgr->calcBlockHeat(p, seed, timeofday, totaltime, use_weather); +} + +weather::humidity_t MapgenEarth::calcBlockHumidity(const v3pos_t &p, uint64_t seed, + float timeofday, float totaltime, bool use_weather) +{ + return m_emerge->biomemgr->calcBlockHumidity( + p, seed, timeofday, totaltime, use_weather); +} diff --git a/src/mapgen/mapgen_earth.h b/src/mapgen/mapgen_earth.h index de92be352..71175fbcf 100644 --- a/src/mapgen/mapgen_earth.h +++ b/src/mapgen/mapgen_earth.h @@ -105,8 +105,20 @@ public: pos_t get_height(pos_t x, pos_t z); ll pos_to_ll(pos_t x, pos_t z); + ll pos_to_ll(const v3pos_t &p); v2pos_t ll_to_pos(const ll &l); - //v2d ll_to_pos_absolute(const ll &l); - void bresenham( - pos_t xa, pos_t za, pos_t xb, pos_t zb, pos_t y, pos_t h, const MapNode &n); + + weather::heat_t calcBlockHeat(const v3pos_t &p, uint64_t seed, float timeofday, + float totaltime, bool use_weather) override; + weather::humidity_t calcBlockHumidity(const v3pos_t &p, uint64_t seed, + float timeofday, float totaltime, bool use_weather) override; + + struct Stat + { + int set{}; + int miss{}; + int level{}; + int check{}; + int fill{}; + } stat; }; diff --git a/src/mapgen/mg_biome.cpp b/src/mapgen/mg_biome.cpp index 738ec3a6a..3aa8e7792 100644 --- a/src/mapgen/mg_biome.cpp +++ b/src/mapgen/mg_biome.cpp @@ -307,7 +307,7 @@ Biome *BiomeGenOriginal::calcBiomeFromNoise(float heat, float humidity, v3s16 po } // Freeminer Weather -s16 BiomeManager::calcBlockHeat(v3pos_t p, uint64_t seed, float timeofday, float totaltime, bool use_weather) { +weather::heat_t BiomeManager::calcBlockHeat(const v3pos_t &p, uint64_t seed, float timeofday, float totaltime, bool use_weather) { //variant 1: full random //f32 heat = NoisePerlin3D(np_heat, p.X, env->getGameTime()/100, p.Z, seed); @@ -334,7 +334,7 @@ s16 BiomeManager::calcBlockHeat(v3pos_t p, uint64_t seed, float timeofday, float return heat; } -s16 BiomeManager::calcBlockHumidity(v3pos_t p, uint64_t seed, float timeofday, float totaltime, bool use_weather) { +weather::humidity_t BiomeManager::calcBlockHumidity(const v3pos_t &p, uint64_t seed, float timeofday, float totaltime, bool use_weather) { auto humidity = NoiseFractal2D(&(mapgen_params->bparams->np_humidity), p.X, p.Z, seed); // auto humidity = calcHumidityAtPoint(p); diff --git a/src/mapgen/mg_biome.h b/src/mapgen/mg_biome.h index 75eefe2c8..2280c51da 100644 --- a/src/mapgen/mg_biome.h +++ b/src/mapgen/mg_biome.h @@ -5,6 +5,7 @@ #pragma once +#include "fm_weather.h" #include "irr_v3d.h" #include "objdef.h" #include "nodedef.h" @@ -245,9 +246,9 @@ public: s32 weather_humidity_height; s32 weather_hot_core; - MapgenParams * mapgen_params = nullptr; - s16 calcBlockHeat(v3pos_t p, uint64_t seed, float timeofday, float totaltime, bool use_weather = 1); - s16 calcBlockHumidity(v3pos_t p, uint64_t seed, float timeofday, float totaltime, bool use_weather = 1); + MapgenParams * mapgen_params{}; + weather::heat_t calcBlockHeat(const v3pos_t &p, uint64_t seed, float timeofday, float totaltime, bool use_weather = 1); + weather::humidity_t calcBlockHumidity(const v3pos_t &p, uint64_t seed, float timeofday, float totaltime, bool use_weather = 1); //==== BiomeGen *createBiomeGen(BiomeGenType type, BiomeParams *params, v3s16 chunksize) diff --git a/src/servermap.h b/src/servermap.h index 51abb6c29..c0099e499 100644 --- a/src/servermap.h +++ b/src/servermap.h @@ -4,6 +4,7 @@ #pragma once +#include "fm_weather.h" #include "irr_v3d.h" #include "mapblock.h" #include "threading/concurrent_set.h" @@ -51,15 +52,12 @@ class ServerMap : public Map { public: - - // freeminer: - using humidity_t = s16; - using heat_t = s16; - virtual heat_t updateBlockHeat(ServerEnvironment *env, const v3pos_t &p, - MapBlock *block = nullptr, unordered_map_v3pos *cache = nullptr, + // freeminer: + virtual weather::heat_t updateBlockHeat(ServerEnvironment *env, const v3pos_t &p, + MapBlock *block = nullptr, unordered_map_v3bpos *cache = nullptr, bool block_add = true); - virtual humidity_t updateBlockHumidity(ServerEnvironment *env, const v3pos_t &p, - MapBlock *block = nullptr, unordered_map_v3pos *cache = nullptr, + virtual weather::humidity_t updateBlockHumidity(ServerEnvironment *env, const v3pos_t &p, + MapBlock *block = nullptr, unordered_map_v3bpos *cache = nullptr, bool block_add = true); size_t transforming_liquid_size(); From 41986e87b947cc4185bcb1d4e85b69af3c714f3a Mon Sep 17 00:00:00 2001 From: proller Date: Mon, 29 Sep 2025 22:37:53 +0200 Subject: [PATCH 02/36] wip --- src/mapgen/earth/arnis-cpp | 2 +- src/mapgen/earth/http.cpp | 11 +++++------ src/mapgen/mapgen_earth.cpp | 2 +- 3 files changed, 7 insertions(+), 8 deletions(-) diff --git a/src/mapgen/earth/arnis-cpp b/src/mapgen/earth/arnis-cpp index d807f189a..211bbcc29 160000 --- a/src/mapgen/earth/arnis-cpp +++ b/src/mapgen/earth/arnis-cpp @@ -1 +1 @@ -Subproject commit d807f189a0fe6d998436e1be31135f212c92e11c +Subproject commit 211bbcc29e545b81a6648d5e1df0576599570ac3 diff --git a/src/mapgen/earth/http.cpp b/src/mapgen/earth/http.cpp index 2ae271735..e9fa837b9 100644 --- a/src/mapgen/earth/http.cpp +++ b/src/mapgen/earth/http.cpp @@ -50,8 +50,8 @@ size_t http_to_file(const std::string &url, const std::string &path) return std::filesystem::file_size(path); }; -size_t multi_http_to_file(const std::string &name, - const std::vector &links, const std::string &path) +size_t multi_http_to_file(const std::string &name, const std::vector &links, + const std::string &path) { static concurrent_set http_failed; if (http_failed.contains(name)) { @@ -70,7 +70,7 @@ size_t multi_http_to_file(const std::string &name, http_failed.insert(name); - errorstream + warningstream << "Not found " << name << "\n" << "try to download manually: \n" << "curl -o " << path << " " @@ -83,8 +83,7 @@ size_t multi_http_to_file(const std::string &name, return std::filesystem::file_size(path); }; -size_t multi_http_to_file( - const std::vector &links, const std::string &path) +size_t multi_http_to_file(const std::vector &links, const std::string &path) { static concurrent_set http_failed; if (http_failed.contains(path)) { @@ -103,7 +102,7 @@ size_t multi_http_to_file( http_failed.emplace(path); - errorstream + warningstream << "Not found " << path << "\n" << "try to download manually: \n" << "curl -o " << path << " " diff --git a/src/mapgen/mapgen_earth.cpp b/src/mapgen/mapgen_earth.cpp index 3243e6748..3334e4d10 100644 --- a/src/mapgen/mapgen_earth.cpp +++ b/src/mapgen/mapgen_earth.cpp @@ -454,7 +454,7 @@ void MapgenEarth::generateBuildings() hdlr->apply(); } - warningstream << "Buildings stat: " << node_min << " set=" << stat.set + verbosestream << "Buildings stat: " << node_min << " set=" << stat.set << " miss=" << stat.miss << " level=" << stat.level << " check=" << stat.check << " fill=" << stat.fill << "\n"; stat = {}; From 9fe3333da506a8119bf76b13f3cc3dc091a42935 Mon Sep 17 00:00:00 2001 From: proller Date: Sun, 5 Oct 2025 19:29:43 +0200 Subject: [PATCH 03/36] earth, fixes --- cmake/Modules/freeminer.cmake | 24 +++++++------ src/client/client.cpp | 5 +++ src/client/fm_client.cpp | 63 ++++++++++++++++++---------------- src/client/hud.cpp | 2 +- src/client/renderingengine.cpp | 4 +-- src/defaultsettings.cpp | 2 +- src/mapgen/earth/arnis-cpp | 2 +- src/mapgen/earth/osmium-inl.h | 15 ++++---- src/mapgen/mapgen_earth.cpp | 4 +-- src/mapgen/mapgen_earth.h | 14 ++++---- src/mapgen/mapgen_v7.cpp | 1 - 11 files changed, 73 insertions(+), 63 deletions(-) diff --git a/cmake/Modules/freeminer.cmake b/cmake/Modules/freeminer.cmake index 6b6701dc1..d7686d415 100644 --- a/cmake/Modules/freeminer.cmake +++ b/cmake/Modules/freeminer.cmake @@ -119,34 +119,36 @@ if(NOT MSVC) if("${CMAKE_GENERATOR}" STREQUAL "Ninja" ) if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang") - set(OTHER_FLAGS "${OTHER_FLAGS} -fdiagnostics-color") + add_compile_options(-fdiagnostics-color) elseif ( CMAKE_COMPILER_IS_GNUCC AND CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 4.8 ) - set(OTHER_FLAGS "${OTHER_FLAGS} -fdiagnostics-color=always") + add_compile_options(-fdiagnostics-color=always) endif () endif () if(SANITIZE_ADDRESS) message(STATUS "Build with sanitize=address") - set(OTHER_FLAGS "${OTHER_FLAGS} -fsanitize=address -fno-omit-frame-pointer -fno-optimize-sibling-calls") - set(ENABLE_SYSTEM_JSONCPP 0) + add_compile_options(-fsanitize=address -fno-omit-frame-pointer -fno-optimize-sibling-calls) + add_link_options(-fsanitize=address) + set(ENABLE_SYSTEM_JSONCPP 0) endif() if(SANITIZE_THREAD) message(STATUS "Build with sanitize=thread") - set(OTHER_FLAGS "${OTHER_FLAGS} -fsanitize=thread -fPIE -fno-omit-frame-pointer -fno-optimize-sibling-calls") + add_compile_options(-fsanitize=thread -fPIE -fno-omit-frame-pointer -fno-optimize-sibling-calls) + add_link_options(-fsanitize=thread -fPIE) if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") - set(OTHER_FLAGS "${OTHER_FLAGS} -pie") + add_compile_options(-pie) endif() set(ENABLE_SYSTEM_JSONCPP 0) endif() if(SANITIZE_MEMORY) message(STATUS "Build with sanitize=memory") - set(OTHER_FLAGS "${OTHER_FLAGS} -fsanitize=memory -fPIE -fno-omit-frame-pointer -fno-optimize-sibling-calls") - SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -pie") + add_compile_options(-fsanitize=memory -fPIE -fno-omit-frame-pointer -fno-optimize-sibling-calls) + add_link_options(-fsanitize=memory -pie) set(ENABLE_SYSTEM_JSONCPP 0) endif() if(SANITIZE_UNDEFINED) - message(STATUS "Build with sanitize=undefined ") - set(OTHER_FLAGS "${OTHER_FLAGS} -fsanitize=undefined -fno-omit-frame-pointer -fno-optimize-sibling-calls") + add_compile_options(-fsanitize=undefined -fno-omit-frame-pointer -fno-optimize-sibling-calls) + add_link_options(-fsanitize=undefined) set(ENABLE_SYSTEM_JSONCPP 0) endif() @@ -182,7 +184,7 @@ if(NOT MSVC) if (TCMALLOC_LIBRARY) set(PLATFORM_LIBS ${PLATFORM_LIBS} ${TCMALLOC_LIBRARY}) - set(OTHER_FLAGS "${OTHER_FLAGS} -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-free") + add_compile_options(-fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-free) endif() message(STATUS "Build with tcmalloc ${TCMALLOC_LIBRARY} ${PROFILER_LIBRARY}") diff --git a/src/client/client.cpp b/src/client/client.cpp index 270c74f2e..3ecac0f5a 100644 --- a/src/client/client.cpp +++ b/src/client/client.cpp @@ -368,6 +368,7 @@ void Client::Stop() // TODO: correct order: mesh_thread_pool.wait_until_empty(); farmesh_async.wait(); + mesh_thread_pool.wait_until_nothing_in_flight(); mesh_thread_pool.wait_until_empty(); farmesh.reset(); farmesh_async.wait(); @@ -396,6 +397,7 @@ Client::~Client() std::this_thread::sleep_for(std::chrono::milliseconds(100)); } } + mesh_thread_pool.wait_until_nothing_in_flight(); mesh_thread_pool.wait_until_empty(); // before ~ClientMap() deleteAuthData(); @@ -407,6 +409,9 @@ Client::~Client() updateDrawList_async.wait(); update_shadows_async.wait(); + mesh_thread_pool.wait_until_nothing_in_flight(); + mesh_thread_pool.wait_until_empty(); // before ~ClientMap() + /* MeshUpdateResult r; while (m_mesh_update_manager->getNextResult(r)) { diff --git a/src/client/fm_client.cpp b/src/client/fm_client.cpp index b23869475..6248dec30 100644 --- a/src/client/fm_client.cpp +++ b/src/client/fm_client.cpp @@ -203,39 +203,42 @@ void Client::handleCommand_BlockDataFm(NetworkPacket *pkt) if (!block) block = m_env.getMap().createBlankBlock(bpos); } - const auto lock = block->lock_unique_rec(); - block->far_step = step; - content_t content_only{}; - packet.convert_safe(TOCLIENT_BLOCKDATA_CONTENT_ONLY, content_only); - block->content_only = content_only; - packet.convert_safe( - TOCLIENT_BLOCKDATA_CONTENT_ONLY_PARAM1, block->content_only_param1); - packet.convert_safe( - TOCLIENT_BLOCKDATA_CONTENT_ONLY_PARAM2, block->content_only_param2); + { + const auto lock = block->lock_unique_rec(); + block->far_step = step; + content_t content_only{}; + packet.convert_safe(TOCLIENT_BLOCKDATA_CONTENT_ONLY, content_only); + block->content_only = content_only; + packet.convert_safe( + TOCLIENT_BLOCKDATA_CONTENT_ONLY_PARAM1, block->content_only_param1); + packet.convert_safe( + TOCLIENT_BLOCKDATA_CONTENT_ONLY_PARAM2, block->content_only_param2); - if (block->content_only == CONTENT_IGNORE) { - try { - block->deSerialize(istr, m_server_ser_ver, false); - } catch (const std::exception &ex) { - errorstream << "fm block deSerialize fail " << bpos << " " << block->far_step - << " : " << ex.what() << " : " << pkt->getSize() << " " - << packet.size() << " v=" << (short)m_server_ser_ver << "\n"; + if (block->content_only == CONTENT_IGNORE) { + try { + block->deSerialize(istr, m_server_ser_ver, false); + } catch (const std::exception &ex) { + errorstream << "fm block deSerialize fail " << bpos << " " + << block->far_step << " : " << ex.what() << " : " + << pkt->getSize() << " " << packet.size() + << " v=" << (short)m_server_ser_ver << "\n"; #if !NDEBUG - errorstream << "bad data " << istr.str().size() << " : " << istr.str() - << "\n"; + errorstream << "bad data " << istr.str().size() << " : " << istr.str() + << "\n"; #endif - return; + return; + } + } else { + block->fill({block->content_only, block->content_only_param1, + block->content_only_param2}); } - } else { - block->fill({block->content_only, block->content_only_param1, - block->content_only_param2}); + s32 h = 0; // for convert to atomic + packet[TOCLIENT_BLOCKDATA_HEAT].convert(h); + block->heat = h; + h = 0; + packet[TOCLIENT_BLOCKDATA_HUMIDITY].convert(h); + block->humidity = h; } - s32 h = 0; // for convert to atomic - packet[TOCLIENT_BLOCKDATA_HEAT].convert(h); - block->heat = h; - h = 0; - packet[TOCLIENT_BLOCKDATA_HUMIDITY].convert(h); - block->humidity = h; if (m_localdb && !is_simple_singleplayer_game) { if (const auto db = GetFarDatabase({}, far_dbases, m_world_path, step); db) { @@ -253,7 +256,7 @@ void Client::handleCommand_BlockDataFm(NetworkPacket *pkt) block->content_only != CONTENT_AIR) { if (getNodeBlockPos(floatToInt(m_env.getLocalPlayer()->getPosition(), BS)) .getDistanceFrom(bpos) <= 1) - addUpdateMeshTaskWithEdge(bpos); + addUpdateMeshTaskWithEdge(bpos); } } else { static thread_local const auto settings_farmesh_server = @@ -290,7 +293,7 @@ void Client::handleCommand_BlockDataFm(NetworkPacket *pkt) } createFarMesh(block); auto &far_blocks = client_map.m_far_blocks; - + const auto lock = far_blocks.lock_unique_rec(); if (const auto &it = far_blocks.find(bpos); it != far_blocks.end()) { if (it->second->far_step != block->far_step) { diff --git a/src/client/hud.cpp b/src/client/hud.cpp index efdd66395..2a4c9f0c4 100644 --- a/src/client/hud.cpp +++ b/src/client/hud.cpp @@ -939,7 +939,7 @@ void Hud::drawBlockBounds() u16 mesh_chunk_size = std::max(1, g_settings->getU16("client_mesh_chunk")); - v3s16 pos = player->getStandingNodePos(); + // 3s16 pos = player->getStandingNodePos(); if (m_block_bounds_mode == BLOCK_BOUNDS_FAR_DRAWN) { const auto offset = intToFloat(client->getCamera()->getOffset(), BS); diff --git a/src/client/renderingengine.cpp b/src/client/renderingengine.cpp index 7b04c5b6f..1d73f6e0e 100644 --- a/src/client/renderingengine.cpp +++ b/src/client/renderingengine.cpp @@ -36,7 +36,7 @@ void FpsControl::reset() void FpsControl::limit(IrrlichtDevice *device, f32 *dtime) { - const float fps_limit = device->isWindowFocused() + static thread_local const float fps_limit = device->isWindowFocused() ? g_settings->getFloat("fps_max") : g_settings->getFloat("fps_max_unfocused"); const u64 frametime_min = 1000000.0f / std::max(fps_limit, 1.0f); @@ -312,7 +312,7 @@ void RenderingEngine::draw_load_screen(const std::wstring &text, driver->setFog(RenderingEngine::MENU_SKY_COLOR); driver->beginScene(true, true, RenderingEngine::MENU_SKY_COLOR); - if (g_settings->getBool("menu_clouds")) { + if (static thread_local const auto menu_clouds = g_settings->getBool("menu_clouds"); menu_clouds) { g_menuclouds->step(dtime * 3); g_menucloudsmgr->drawAll(); } diff --git a/src/defaultsettings.cpp b/src/defaultsettings.cpp index 271ae8583..49563bc33 100644 --- a/src/defaultsettings.cpp +++ b/src/defaultsettings.cpp @@ -245,7 +245,7 @@ void fm_set_default_settings(Settings *settings) { settings->setDefault("emergequeue_limit_diskonly", ""); // autodetect from number of cpus settings->setDefault("emergequeue_limit_generate", ""); // autodetect from number of cpus settings->setDefault("emergequeue_limit_total", ""); // autodetect from number of cpus - // settings->setDefault("num_emerge_threads", ""); // "1" // Fix and enable auto + settings->setDefault("num_emerge_threads", ""); // "1" // Fix and enable auto settings->setDefault("server_map_save_interval", "300"); // "5.3" settings->setDefault("sqlite_synchronous", "1"); // "2" settings->setDefault("save_generated_block", "true"); diff --git a/src/mapgen/earth/arnis-cpp b/src/mapgen/earth/arnis-cpp index 211bbcc29..7f1cba84a 160000 --- a/src/mapgen/earth/arnis-cpp +++ b/src/mapgen/earth/arnis-cpp @@ -1 +1 @@ -Subproject commit 211bbcc29e545b81a6648d5e1df0576599570ac3 +Subproject commit 7f1cba84aa53fa708fe19a3bdbc4155b7261345d diff --git a/src/mapgen/earth/osmium-inl.h b/src/mapgen/earth/osmium-inl.h index c16a6eec3..6377367a8 100644 --- a/src/mapgen/earth/osmium-inl.h +++ b/src/mapgen/earth/osmium-inl.h @@ -183,11 +183,8 @@ public: class MyHandler : public osmium::handler::Handler { - MapgenEarth *mg; - const bool todo{false}; - public: - MyHandler(MapgenEarth *mg) : mg{mg} {} + MapgenEarth *mg{}; void way(const osmium::Way &way) { @@ -225,6 +222,9 @@ public: std::vector v; for (const auto &r : relation) { } + for (const auto &sn : relation.subitems()) { + way(sn); + } arnis::generate_world(editor, v); } }; @@ -234,20 +234,19 @@ class hdl : public handler_i osmium::Location>; using cache_t = osmium::handler::NodeLocationsForWays; - MapgenEarth *mg{}; const std::string path_name; MyHandler handler; public: hdl(MapgenEarth *mg, const std::string &path_name) : - mg{mg}, path_name{path_name}, handler{mg} + path_name{path_name} { } ~hdl() = default; - void apply() override + void apply(MapgenEarth *mg) override { osmium::area::Assembler::config_type assembler_config; assembler_config.create_empty_areas = false; @@ -260,7 +259,6 @@ public: { const auto llmin = mg->pos_to_ll(mg->node_min.X, mg->node_min.Z); const auto llmax = mg->pos_to_ll(mg->node_max.X, mg->node_max.Z); - } osmium::io::File file{path_name, "pbf"}; osmium::relations::read_relations(file, mp_manager); @@ -272,6 +270,7 @@ public: } arnis::init(mg); + handler.mg = mg; osmium::apply(reader, cache, handler, mp_manager.handler([&handler = this->handler]( const osmium::memory::Buffer &area_buffer) { diff --git a/src/mapgen/mapgen_earth.cpp b/src/mapgen/mapgen_earth.cpp index 3334e4d10..a2de5cada 100644 --- a/src/mapgen/mapgen_earth.cpp +++ b/src/mapgen/mapgen_earth.cpp @@ -451,13 +451,13 @@ void MapgenEarth::generateBuildings() } if (const auto &hdlr = maps_holder->osm_bbox.get(bbox)) { - hdlr->apply(); + hdlr->apply(this); } verbosestream << "Buildings stat: " << node_min << " set=" << stat.set << " miss=" << stat.miss << " level=" << stat.level << " check=" << stat.check << " fill=" << stat.fill << "\n"; - stat = {}; + stat.clean(); #endif } diff --git a/src/mapgen/mapgen_earth.h b/src/mapgen/mapgen_earth.h index 71175fbcf..eea5c204e 100644 --- a/src/mapgen/mapgen_earth.h +++ b/src/mapgen/mapgen_earth.h @@ -21,6 +21,7 @@ along with Freeminer. If not, see . #pragma once +#include #include #include #include @@ -64,7 +65,7 @@ class MapgenEarth; class handler_i { public: - virtual void apply() = 0; + virtual void apply(MapgenEarth*) = 0; }; struct maps_holder_t @@ -115,10 +116,11 @@ public: struct Stat { - int set{}; - int miss{}; - int level{}; - int check{}; - int fill{}; + std::atomic_int set{}; + std::atomic_int miss{}; + std::atomic_int level{}; + std::atomic_int check{}; + std::atomic_int fill{}; + void clean() { set = miss = level = check = fill = 0; } } stat; }; diff --git a/src/mapgen/mapgen_v7.cpp b/src/mapgen/mapgen_v7.cpp index e776fa704..0e8dbc554 100644 --- a/src/mapgen/mapgen_v7.cpp +++ b/src/mapgen/mapgen_v7.cpp @@ -330,7 +330,6 @@ int MapgenV7::getSpawnLevelAtPoint(v2s16 p) return MAX_MAP_GENERATION_LIMIT; } - void MapgenV7::makeChunk(BlockMakeData *data) { // Pre-conditions From f62377914085ec6149ed681a2b5e88567ff5eb63 Mon Sep 17 00:00:00 2001 From: proller Date: Sun, 5 Oct 2025 20:49:53 +0200 Subject: [PATCH 04/36] fix --- games/default | 2 +- src/mapgen/earth/blocks.cpp | 62 ++++++------------------------------- 2 files changed, 10 insertions(+), 54 deletions(-) diff --git a/games/default b/games/default index d9f6ce190..af6935757 160000 --- a/games/default +++ b/games/default @@ -1 +1 @@ -Subproject commit d9f6ce19098392e729c8b253a94592c188917b5e +Subproject commit af693575799508aa672c9679b9639af4df772051 diff --git a/src/mapgen/earth/blocks.cpp b/src/mapgen/earth/blocks.cpp index 2ddaa9ab1..39807db8a 100644 --- a/src/mapgen/earth/blocks.cpp +++ b/src/mapgen/earth/blocks.cpp @@ -213,7 +213,7 @@ void init(MapgenEarth *mg) ANDESITE = def; BIRCH_LEAVES = g("default:leaves"); BIRCH_LOG = g("default:tree"); - BLACK_CONCRETE = def; + BLACK_CONCRETE = g("default:obsidian"); BLACKSTONE = def; BLUE_FLOWER = g("flowers:geranium"); BLUE_TERRACOTTA = def; @@ -239,13 +239,13 @@ void init(MapgenEarth *mg) GRASS_BLOCK = g("default:grass_5"); GRASS = g("default:grass_3"); GRAVEL = g("default:gravel"); - GRAY_CONCRETE = def; + GRAY_CONCRETE = g("default:stone"); // TODO GRAY_TERRACOTTA = def; GREEN_STAINED_HARDENED_CLAY = def; GREEN_WOOL = g("wool:green"); HAY_BALE = def; IRON_BARS = g("default:stone_with_iron"); - IRON_BLOCK = g("default:stone_with_iron"); + IRON_BLOCK = g("default:steelblock"); // TODO JUNGLE_PLANKS = g("default:wood"); LADDER = g("default:ladder_wood"); LIGHT_BLUE_CONCRETE = def; @@ -285,18 +285,18 @@ void init(MapgenEarth *mg) SMOOTH_QUARTZ = def; SMOOTH_RED_SANDSTONE = def; SMOOTH_SANDSTONE = def; - SMOOTH_STONE = def; + SMOOTH_STONE = g("default:stone"); SPONGE = g("sponge:sponge"); SPRUCE_LOG = def; SPRUCE_PLANKS = g("default:wood"); - STONE_BLOCK_SLAB = def; - STONE_BRICK_SLAB = def; + STONE_BLOCK_SLAB = g("default:stone"); + STONE_BRICK_SLAB = g("default:cobble"); STONE_BRICKS = def; - STONE = def; + STONE = g("default:stone"); TERRACOTTA = def; WARPED_PLANKS = def; WATER = g("default:water_source"); - WHITE_CONCRETE = def; + WHITE_CONCRETE = g("default:stone"); // TODO WHITE_FLOWER = g("flowers:dandelion_white"); WHITE_STAINED_GLASS = GLASS; WHITE_TERRACOTTA = def; @@ -340,7 +340,7 @@ void init(MapgenEarth *mg) GOLD_ORE = g("default:stone_with_gold"); COPPER_ORE = g("default:stone_with_copper"); CLAY = g("default:clay"); - DIRT_PATH = g("default:dirt"); + DIRT_PATH = g("default:dirt_with_grass_footsteps"); ICE = g("default:ice"); PACKED_ICE = g("default:ice"); MUD = g("default:dirt"); @@ -386,50 +386,6 @@ void init(MapgenEarth *mg) QUARTZ_STAIRS = STONE_BRICK_STAIRS; POLISHED_ANDESITE_STAIRS = STONE_BRICK_STAIRS; NETHER_BRICK_STAIRS = STONE_BRICK_STAIRS; - - // TODO: find better in mods - - AIR = g("air"); - BLACK_CONCRETE = g("default:obsidian"); // ? - BRICK = g("default:brick"); - COBBLESTONE = g("default:cobble"); - COBBLESTONE_WALL = g("default:cobble"); - DIRT = g("default:dirt"); - DIRT_PATH = g("default:dry_dirt"); - GLASS = g("default:glass"); - GLOWSTONE = g("default:stone"); - GRASS_BLOCK = g("default:dirt_with_grass"); - GRAVEL = g("default:gravel"); - GRAY_CONCRETE = g("default:stone"); // TODO - //GREEN_WOOL = g("wool:green"); - IRON_BLOCK = g("default:steelblock"); // TODO - LIGHT_GRAY_CONCRETE = g("default:cobble"); // TODO - OAK_FENCE = g("default:wood"); - //OAK_FENCE_GATE = g("default:wood"); - //OAK_LEAVES = g("default:leaves"); - OAK_LOG = g("default:tree"); // TODO - OAK_PLANKS = g("default:wood"); - //RAIL_EAST_WEST = g("default:rail"); - //RAIL_NORTH_EAST = g("default:rail"); - //RAIL_NORTH_SOUTH = g("default:rail"); - //RAIL_NORTH_WEST = g("default:rail"); - //RAIL_SOUTH_EAST = g("default:rail"); - //RAIL_SOUTH_WEST = g("default:rail"); - //RED_WOOL = g("wool:red"); - SAND = g("default:sand"); - SANDSTONE = g("default:sandstone"); - SMOOTH_STONE = g("default:stone"); - SMOOTH_STONE_BLOCK = g("default:stone"); //TODO - SNOW_LAYER = g("default:snow"); - STONE = g("default:stone"); - STONE_BLOCK_SLAB = g("default:stone"); - STONE_BRICK_SLAB = g("default:cobble"); - STONE_BRICKS = g("default:cobble"); - WHITE_CONCRETE = g("default:stone"); // TODO - WHITE_STAINED_GLASS = g("default:glass"); // ? - //WHITE_WOOL = g("wool:white"); - //YELLOW_WOOL = g("wool:yellow"); - //WATER = g("default:water"); } } From 52334ad7d44007dc7b4a3dccb5d447a33f54b16a Mon Sep 17 00:00:00 2001 From: proller Date: Mon, 6 Oct 2025 22:37:55 +0200 Subject: [PATCH 05/36] fix --- src/mapgen/mapgen_earth.cpp | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/src/mapgen/mapgen_earth.cpp b/src/mapgen/mapgen_earth.cpp index a2de5cada..ed0d4d1ac 100644 --- a/src/mapgen/mapgen_earth.cpp +++ b/src/mapgen/mapgen_earth.cpp @@ -23,34 +23,37 @@ along with Freeminer. If not, see . #include #include #include -#include #include #include #include #include "debug/dump.h" +#include "emerge.h" #include "filesys.h" #include "irr_v2d.h" +#include "irr_v3d.h" #include "irrlichttypes.h" +#include "log_types.h" +#include "log.h" +#include "map.h" +#include "mapblock.h" +#include "mapgen_earth.h" #include "mapgen/earth/hgt.h" #include "mapgen/earth/http.h" -#include "mapgen_earth.h" -#include "voxel.h" -#include "mapblock.h" #include "mapnode.h" -#include "map.h" -#include "nodedef.h" -#include "voxelalgorithms.h" -#include "settings.h" -#include "emerge.h" -#include "serverenvironment.h" #include "mg_biome.h" -#include "log_types.h" +#include "nodedef.h" +#include "serverenvironment.h" +#include "settings.h" +#include "voxel.h" +#include "voxelalgorithms.h" #if USE_OSMIUM +#include "earth/osmium-inl.h" #include #include #include #include +#include #include #include #include @@ -59,9 +62,6 @@ along with Freeminer. If not, see . #include #include #include - -#include "earth/osmium-inl.h" - #endif std::unique_ptr MapgenEarth::maps_holder; From d64fad12a8ce21830a6be86e2939ae5ee81ba5c0 Mon Sep 17 00:00:00 2001 From: proller Date: Mon, 6 Oct 2025 23:32:08 +0200 Subject: [PATCH 06/36] fix --- src/mapgen/mapgen_earth.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/mapgen/mapgen_earth.cpp b/src/mapgen/mapgen_earth.cpp index ed0d4d1ac..24192a84a 100644 --- a/src/mapgen/mapgen_earth.cpp +++ b/src/mapgen/mapgen_earth.cpp @@ -465,8 +465,10 @@ void MapgenEarth::generateBuildings() weather::heat_t MapgenEarth::calcBlockHeat(const v3pos_t &p, uint64_t seed, float timeofday, float totaltime, bool use_weather) { +#if USE_OSMIUM const auto ll = pos_to_ll(p); const auto tile = osmium::geom::Tile(3, osmium::Location(ll.lon, ll.lat)); +#endif return m_emerge->biomemgr->calcBlockHeat(p, seed, timeofday, totaltime, use_weather); } From 648c00ccde9d93d83304f4c09bc4e6d2fe86692c Mon Sep 17 00:00:00 2001 From: proller Date: Fri, 10 Oct 2025 04:50:48 +0200 Subject: [PATCH 07/36] fix --- src/fm_map.cpp | 6 +++--- src/servermap.cpp | 4 ++-- src/servermap.h | 2 +- util/autotest/auto.pl | 3 ++- 4 files changed, 8 insertions(+), 7 deletions(-) diff --git a/src/fm_map.cpp b/src/fm_map.cpp index b7d775377..cb1d08c7e 100644 --- a/src/fm_map.cpp +++ b/src/fm_map.cpp @@ -375,7 +375,7 @@ weather::humidity_t ServerMap::updateBlockHumidity(ServerEnvironment *env, int ServerMap::getSurface(const v3pos_t &basepos, int searchup, bool walkable_only) { - s16 max = MYMIN(searchup + basepos.Y, 0x7FFF); + pos_t max = MYMIN(searchup + basepos.Y, 0x7FFF); MapNode last_node = getNode(basepos); MapNode node = last_node; @@ -1329,7 +1329,7 @@ bool ServerMap::propagateSunlight( } //#endif -void ServerMap::lighting_modified_add(const v3pos_t &pos, int range) +void ServerMap::lighting_modified_add(const v3bpos_t &pos, int range) { MutexAutoLock lock(m_lighting_modified_mutex); if (m_lighting_modified_blocks.contains(pos)) { @@ -1414,7 +1414,7 @@ MapNode Map::getNodeNoEx(v3pos_t p) { * Get the ground level by searching for a non CONTENT_AIR node in a column from top to * bottom */ -s16 ServerMap::findGroundLevel(v2pos_t p2d, bool cacheBlocks) +pos_t ServerMap::findGroundLevel(v2pos_t p2d, bool cacheBlocks) { pos_t level; diff --git a/src/servermap.cpp b/src/servermap.cpp index dff402aed..16ba2e76b 100644 --- a/src/servermap.cpp +++ b/src/servermap.cpp @@ -334,8 +334,8 @@ void ServerMap::finishBlockMake(BlockMakeData *data, if (save_generated_block) block->raiseModified(MOD_STATE_WRITE_NEEDED, MOD_REASON_EXPIRE_IS_AIR, false); - else - block->setLightingComplete(0); + + block->setLightingComplete(0); } ServerEnvironment *senv = &((Server *)m_gamedef)->getEnv(); diff --git a/src/servermap.h b/src/servermap.h index c0099e499..966992ddb 100644 --- a/src/servermap.h +++ b/src/servermap.h @@ -84,7 +84,7 @@ public: std::mutex m_lighting_modified_mutex; std::map m_lighting_modified_blocks; std::map m_lighting_modified_blocks_range; - void lighting_modified_add(const v3pos_t &pos, int range = 5); + void lighting_modified_add(const v3bpos_t &pos, int range = 5); void unspreadLight(enum LightBank bank, std::map &from_nodes, std::set &light_sources, diff --git a/util/autotest/auto.pl b/util/autotest/auto.pl index ff33c96c7..bf2bb3485 100755 --- a/util/autotest/auto.pl +++ b/util/autotest/auto.pl @@ -214,7 +214,8 @@ our $options = { profiler_max_page => 1, profiler_page => 1, debug_log_level => 'info', - movement_speed_fast => 10000, + movement_speed_fast => 100000, + movement_acceleration_fast => 100, max_block_send_distance => 100, default_privs => 'interact, shout, teleport, settime, privs, fly, noclip, fast, debug', default_privs_creative => 'interact, shout, teleport, settime, privs, fly, noclip, fast, debug', From e785e70aaa9f3d1f42890ced8111618fdab43d5e Mon Sep 17 00:00:00 2001 From: proller Date: Sat, 11 Oct 2025 14:44:53 +0200 Subject: [PATCH 08/36] fix ws --- src/constants.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/constants.h b/src/constants.h index 844607f3c..1eb036aaf 100644 --- a/src/constants.h +++ b/src/constants.h @@ -23,7 +23,7 @@ #define PEER_MINETEST_MIN 2 #define PEER_MINETEST_MAX 9999 #define PEER_WS_MIN 10002 -#define PEER_WS_MAX 19999 +#define PEER_WS_MAX 0x3fff-1 // MAX_UDP_PEERS #define PEER_ENET_MIN 20002 #define PEER_ENET_MAX 29999 #define PEER_SCTP_MIN 30002 From 1c7124914a2f712d306fd2226c085a17061e03f9 Mon Sep 17 00:00:00 2001 From: proller Date: Mon, 13 Oct 2025 03:29:51 +0200 Subject: [PATCH 09/36] better --- src/client/fm_client.cpp | 13 ++--- src/client/mapblock_mesh.h | 3 +- src/fm_map.cpp | 2 + src/fm_server.cpp | 7 +-- src/fm_world_merge.cpp | 18 +++++-- src/mapgen/earth/arnis_adapter.h | 3 ++ src/network/fm_networkprotocol.h | 88 ++++++++++++++++---------------- src/servermap.cpp | 1 + 8 files changed, 76 insertions(+), 59 deletions(-) diff --git a/src/client/fm_client.cpp b/src/client/fm_client.cpp index 6248dec30..ec9f46c5e 100644 --- a/src/client/fm_client.cpp +++ b/src/client/fm_client.cpp @@ -7,6 +7,7 @@ #include "client/mapblock_mesh.h" #include "clientmap.h" #include "emerge.h" +#include "fm_weather.h" #include "fm_world_merge.h" #include "irr_v3d.h" #include "log.h" @@ -232,12 +233,12 @@ void Client::handleCommand_BlockDataFm(NetworkPacket *pkt) block->fill({block->content_only, block->content_only_param1, block->content_only_param2}); } - s32 h = 0; // for convert to atomic - packet[TOCLIENT_BLOCKDATA_HEAT].convert(h); - block->heat = h; - h = 0; - packet[TOCLIENT_BLOCKDATA_HUMIDITY].convert(h); - block->humidity = h; + weather::heat_t heat = 0; // for convert to atomic + packet[TOCLIENT_BLOCKDATA_HEAT].convert(heat); + block->heat = heat; + weather::humidity_t humidity = 0; + packet[TOCLIENT_BLOCKDATA_HUMIDITY].convert(humidity); + block->humidity = humidity; } if (m_localdb && !is_simple_singleplayer_game) { diff --git a/src/client/mapblock_mesh.h b/src/client/mapblock_mesh.h index 6c9ad2c63..a89c517a2 100644 --- a/src/client/mapblock_mesh.h +++ b/src/client/mapblock_mesh.h @@ -253,8 +253,7 @@ public: m_animation_force_timer--; } - -// fm: + // fm: /*u32 getUsageTimer() { return m_usage_timer; } diff --git a/src/fm_map.cpp b/src/fm_map.cpp index cb1d08c7e..5db430c92 100644 --- a/src/fm_map.cpp +++ b/src/fm_map.cpp @@ -513,6 +513,8 @@ u32 Map::timerUpdate(float uptime, float unload_timeout, s32 max_loaded_blocks, } if (block->getUsageTimer() > unload_timeout) { // block->refGet() <= 0 && const v3bpos_t p = block->getPos(); + changed_blocks_for_merge.emplace(p); + // infostream<<" deleting block p="<. #include "database/database.h" #include "emerge.h" #include "filesys.h" +#include "fm_weather.h" #include "irrlichttypes.h" #include "porting.h" #include "fm_world_merge.h" @@ -698,8 +699,8 @@ void Server::SendBlockFm(session_t peer_id, MapBlockPtr block, u8 ver, block->serializeNetworkSpecific(os); PACK(TOCLIENT_BLOCKDATA_DATA, os.str()); - PACK(TOCLIENT_BLOCKDATA_HEAT, (s16)(block->heat + block->heat_add)); - PACK(TOCLIENT_BLOCKDATA_HUMIDITY, (s16)(block->humidity + block->humidity_add)); + PACK(TOCLIENT_BLOCKDATA_HEAT, (weather::heat_t)(block->heat + block->heat_add)); + PACK(TOCLIENT_BLOCKDATA_HUMIDITY, (weather::humidity_t)(block->humidity + block->humidity_add)); PACK(TOCLIENT_BLOCKDATA_STEP, block->far_step); PACK(TOCLIENT_BLOCKDATA_CONTENT_ONLY, block->content_only.load(std::memory_order_relaxed)); @@ -755,7 +756,7 @@ void *WorldMergeThread::run() .ndef{m_server->getNodeDefManager()}, .smap{m_server->getEnv().m_map.get()}, .far_dbases{m_server->far_dbases}, - .dbase{m_server->getEnv().m_map->m_db.dbase, [](MapDatabase*){}}, + .dbase{m_server->getEnv().m_map->m_db.dbase, [](MapDatabase *) {}}, .save_dir{m_server->getEnv().m_map->m_savedir}, }; diff --git a/src/fm_world_merge.cpp b/src/fm_world_merge.cpp index d1816836a..6b94d6b77 100644 --- a/src/fm_world_merge.cpp +++ b/src/fm_world_merge.cpp @@ -80,9 +80,18 @@ void WorldMerger::merge_one_block(MapDatabase *dbase, MapDatabase *dbase_up, const v3pos_t rpos(x, y, z); const v3bpos_t nbpos(bpos_aligned.X + (x << step), bpos_aligned.Y + (y << step), bpos_aligned.Z + (z << step)); - auto nblock = load_block(smap, dbase, nbpos); + MapBlockPtr nblock; + if (!step) { + const auto block = smap->getBlock(nbpos); + if (block && block->isGenerated()) { + nblock = block; + } + } if (!nblock) { - continue; + nblock = load_block(smap, dbase, nbpos); + if (!nblock || !nblock->isGenerated()) { + continue; + } } if (const auto ts = nblock->getActualTimestamp(); ts > timestamp) timestamp = ts; @@ -136,7 +145,7 @@ void WorldMerger::merge_one_block(MapDatabase *dbase, MapDatabase *dbase_up, std::vector top_light_night; std::unordered_map nodes; - // TODO: tune block selector + // TODO: tune block selector #if 0 // Simple grid aligned @@ -156,7 +165,8 @@ void WorldMerger::merge_one_block(MapDatabase *dbase, MapDatabase *dbase_up, v3pos_t{1, 0, 1}, v3pos_t{1, 1, 1}, }) { - const auto &n = block->getNodeNoLock(lpos + dir); + const auto p = lpos + dir; + const auto &n = block->getNodeNoLock(p); const auto c = n.getContent(); if (c == CONTENT_IGNORE) { continue; diff --git a/src/mapgen/earth/arnis_adapter.h b/src/mapgen/earth/arnis_adapter.h index 8f1b09e32..b1a5a1cbb 100644 --- a/src/mapgen/earth/arnis_adapter.h +++ b/src/mapgen/earth/arnis_adapter.h @@ -262,6 +262,9 @@ struct Ground { ++mg->stat.level; const auto h = mg->get_height(pos.X, pos.Y); + if (h < 1) { + return 1; + } return h; } }; diff --git a/src/network/fm_networkprotocol.h b/src/network/fm_networkprotocol.h index de84d6794..053fe25a5 100644 --- a/src/network/fm_networkprotocol.h +++ b/src/network/fm_networkprotocol.h @@ -38,25 +38,25 @@ enum TOCLIENT_BLOCKDATA_STEP, TOCLIENT_BLOCKDATA_CONTENT_ONLY, TOCLIENT_BLOCKDATA_CONTENT_ONLY_PARAM1, - TOCLIENT_BLOCKDATA_CONTENT_ONLY_PARAM2 + TOCLIENT_BLOCKDATA_CONTENT_ONLY_PARAM2, }; enum { TOCLIENT_ADDNODE_POS, TOCLIENT_ADDNODE_NODE, - TOCLIENT_ADDNODE_REMOVE_METADATA + TOCLIENT_ADDNODE_REMOVE_METADATA, }; enum { - TOCLIENT_REMOVENODE_POS + TOCLIENT_REMOVENODE_POS, }; enum { // string, serialized inventory - TOCLIENT_INVENTORY_DATA + TOCLIENT_INVENTORY_DATA, }; enum @@ -64,13 +64,13 @@ enum // u16 time (0-23999) TOCLIENT_TIME_OF_DAY_TIME, // f32 time_speed - TOCLIENT_TIME_OF_DAY_TIME_SPEED + TOCLIENT_TIME_OF_DAY_TIME_SPEED, }; enum { // string - TOCLIENT_CHAT_MESSAGE_DATA + TOCLIENT_CHAT_MESSAGE_DATA, }; enum @@ -78,7 +78,7 @@ enum // list of ids TOCLIENT_ACTIVE_OBJECT_REMOVE_ADD_REMOVE, // list of [id, type, initialization_data] - TOCLIENT_ACTIVE_OBJECT_REMOVE_ADD_ADD + TOCLIENT_ACTIVE_OBJECT_REMOVE_ADD_ADD, }; struct ActiveObjectAddData @@ -114,7 +114,7 @@ enum // f32 pitch TOCLIENT_MOVE_PLAYER_PITCH, // f32 yaw - TOCLIENT_MOVE_PLAYER_YAW + TOCLIENT_MOVE_PLAYER_YAW, // TOCLIENT_MOVE_PLAYER_SPEED }; @@ -125,7 +125,7 @@ enum TOCLIENT_ACCESS_DENIED_CUSTOM_STRING, // u16 command TOCLIENT_ACCESS_DENIED_REASON, - TOCLIENT_ACCESS_DENIED_RECONNECT + TOCLIENT_ACCESS_DENIED_RECONNECT, }; #define TOCLIENT_PUNCH_PLAYER 0x11 @@ -140,13 +140,13 @@ enum // bool set camera point target TOCLIENT_DEATHSCREEN_SET_CAMERA, // v3f camera point target (to point the death cause or whatever) - TOCLIENT_DEATHSCREEN_CAMERA_POINT + TOCLIENT_DEATHSCREEN_CAMERA_POINT, }; enum { // vector> - TOCLIENT_MEDIA_MEDIA + TOCLIENT_MEDIA_MEDIA, }; typedef std::vector> MediaData; @@ -154,7 +154,7 @@ typedef std::vector> MediaData; enum { TOCLIENT_NODEDEF_DEFINITIONS, - TOCLIENT_NODEDEF_DEFINITIONS_ZIP + TOCLIENT_NODEDEF_DEFINITIONS_ZIP, }; enum @@ -162,13 +162,13 @@ enum // list of [string name, string sha1_digest] TOCLIENT_ANNOUNCE_MEDIA_LIST, // string, url of remote media server - TOCLIENT_ANNOUNCE_MEDIA_REMOTE_SERVER + TOCLIENT_ANNOUNCE_MEDIA_REMOTE_SERVER, }; enum { TOCLIENT_ITEMDEF_DEFINITIONS, - TOCLIENT_ITEMDEF_DEFINITIONS_ZIP + TOCLIENT_ITEMDEF_DEFINITIONS_ZIP, }; typedef std::vector> MediaAnnounceList; @@ -188,25 +188,25 @@ enum // u16 TOCLIENT_PLAY_SOUND_OBJECT_ID, // bool - TOCLIENT_PLAY_SOUND_LOOP + TOCLIENT_PLAY_SOUND_LOOP, }; enum { // s32 - TOCLIENT_STOP_SOUND_ID + TOCLIENT_STOP_SOUND_ID, }; enum { // list of strings - TOCLIENT_PRIVILEGES_PRIVILEGES + TOCLIENT_PRIVILEGES_PRIVILEGES, }; enum { // string - TOCLIENT_INVENTORY_FORMSPEC_DATA + TOCLIENT_INVENTORY_FORMSPEC_DATA, }; enum @@ -238,7 +238,7 @@ enum TOCLIENT_MOVEMENT_LIQUID_FLUIDITY_SMOOTH, TOCLIENT_MOVEMENT_LIQUID_SINK, TOCLIENT_MOVEMENT_GRAVITY, - TOCLIENT_MOVEMENT_FALL_AERODYNAMICS + TOCLIENT_MOVEMENT_FALL_AERODYNAMICS, }; enum @@ -278,7 +278,7 @@ enum enum { - TOCLIENT_DELETE_PARTICLESPAWNER_ID + TOCLIENT_DELETE_PARTICLESPAWNER_ID, }; enum @@ -311,38 +311,38 @@ enum TOCLIENT_HUDCHANGE_V3F, TOCLIENT_HUDCHANGE_STRING, TOCLIENT_HUDCHANGE_U32, - TOCLIENT_HUDCHANGE_V2S32 + TOCLIENT_HUDCHANGE_V2S32, }; enum { TOCLIENT_HUD_SET_FLAGS_FLAGS, - TOCLIENT_HUD_SET_FLAGS_MASK + TOCLIENT_HUD_SET_FLAGS_MASK, }; enum { TOCLIENT_HUD_SET_PARAM_ID, - TOCLIENT_HUD_SET_PARAM_VALUE + TOCLIENT_HUD_SET_PARAM_VALUE, }; enum { // u16 breath - TOCLIENT_BREATH_BREATH + TOCLIENT_BREATH_BREATH, }; enum { TOCLIENT_SET_SKY_COLOR, TOCLIENT_SET_SKY_TYPE, - TOCLIENT_SET_SKY_PARAMS + TOCLIENT_SET_SKY_PARAMS, }; enum { TOCLIENT_OVERRIDE_DAY_NIGHT_RATIO_DO, - TOCLIENT_OVERRIDE_DAY_NIGHT_RATIO_VALUE + TOCLIENT_OVERRIDE_DAY_NIGHT_RATIO_VALUE, }; enum @@ -351,13 +351,13 @@ enum TOCLIENT_LOCAL_PLAYER_ANIMATIONS_WALK, TOCLIENT_LOCAL_PLAYER_ANIMATIONS_DIG, TOCLIENT_LOCAL_PLAYER_ANIMATIONS_WALKDIG, - TOCLIENT_LOCAL_PLAYER_ANIMATIONS_FRAME_SPEED + TOCLIENT_LOCAL_PLAYER_ANIMATIONS_FRAME_SPEED, }; enum { TOCLIENT_EYE_OFFSET_FIRST, - TOCLIENT_EYE_OFFSET_THIRD + TOCLIENT_EYE_OFFSET_THIRD, }; enum @@ -366,7 +366,7 @@ enum TOSERVER_INIT_COMPRESSION, TOSERVER_INIT_PROTOCOL_VERSION_MIN, TOSERVER_INIT_PROTOCOL_VERSION_MAX, - TOSERVER_INIT_NAME + TOSERVER_INIT_NAME, }; enum @@ -377,7 +377,7 @@ enum TOSERVER_INIT_LEGACY_PASSWORD, TOSERVER_INIT_LEGACY_PROTOCOL_VERSION_MIN, TOSERVER_INIT_LEGACY_PROTOCOL_VERSION_MAX, - TOSERVER_INIT_LEGACY_PROTOCOL_VERSION_FM + TOSERVER_INIT_LEGACY_PROTOCOL_VERSION_FM, }; enum @@ -391,66 +391,66 @@ enum // f32 TOSERVER_PLAYERPOS_YAW, // u32 - TOSERVER_PLAYERPOS_KEY_PRESSED + TOSERVER_PLAYERPOS_KEY_PRESSED, }; enum { - TOSERVER_DELETEDBLOCKS_DATA + TOSERVER_DELETEDBLOCKS_DATA, }; enum { - TOSERVER_INVENTORY_ACTION_DATA + TOSERVER_INVENTORY_ACTION_DATA, }; enum { - TOSERVER_CHAT_MESSAGE_DATA + TOSERVER_CHAT_MESSAGE_DATA, }; enum { - TOSERVER_DAMAGE_VALUE + TOSERVER_DAMAGE_VALUE, }; enum { TOSERVER_CHANGE_PASSWORD_OLD, - TOSERVER_CHANGE_PASSWORD_NEW + TOSERVER_CHANGE_PASSWORD_NEW, }; enum { - TOSERVER_PLAYERITEM_VALUE + TOSERVER_PLAYERITEM_VALUE, }; enum { - TOSERVER_REMOVED_SOUNDS_IDS + TOSERVER_REMOVED_SOUNDS_IDS, }; enum { TOSERVER_NODEMETA_FIELDS_POS, TOSERVER_NODEMETA_FIELDS_FORMNAME, - TOSERVER_NODEMETA_FIELDS_DATA + TOSERVER_NODEMETA_FIELDS_DATA, }; enum { TOSERVER_INVENTORY_FIELDS_FORMNAME, - TOSERVER_INVENTORY_FIELDS_DATA + TOSERVER_INVENTORY_FIELDS_DATA, }; enum { - TOSERVER_REQUEST_MEDIA_FILES + TOSERVER_REQUEST_MEDIA_FILES, }; enum { - TOSERVER_BREATH_VALUE + TOSERVER_BREATH_VALUE, }; enum @@ -465,7 +465,7 @@ enum */ TOSERVER_INTERACT_ACTION, TOSERVER_INTERACT_ITEM, - TOSERVER_INTERACT_POINTED_THING + TOSERVER_INTERACT_POINTED_THING, }; enum @@ -474,7 +474,7 @@ enum TOSERVER_CLIENT_READY_VERSION_MINOR, TOSERVER_CLIENT_READY_VERSION_PATCH, TOSERVER_CLIENT_READY_VERSION_STRING, - TOSERVER_CLIENT_READY_VERSION_TWEAK + TOSERVER_CLIENT_READY_VERSION_TWEAK, }; // freeminer only packets diff --git a/src/servermap.cpp b/src/servermap.cpp index 16ba2e76b..1aabcdcc4 100644 --- a/src/servermap.cpp +++ b/src/servermap.cpp @@ -352,6 +352,7 @@ void ServerMap::finishBlockMake(BlockMakeData *data, updateBlockHeat(senv, p * MAP_BLOCKSIZE, block); updateBlockHumidity(senv, p * MAP_BLOCKSIZE, block); + changed_blocks_for_merge.emplace(p); // Set timestamp to ensure correct application of LBMs and other stuff block->setTimestampNoChangedFlag(now); From d57a872581dfd498c8785147a38b3801ffb4360b Mon Sep 17 00:00:00 2001 From: proller Date: Mon, 13 Oct 2025 03:37:16 +0200 Subject: [PATCH 10/36] earth catch --- src/mapgen/earth/osmium-inl.h | 77 +++++++------ src/mapgen/mapgen_earth.cpp | 204 ++++++++++++++++++++-------------- src/mapgen/mapgen_earth.h | 5 +- 3 files changed, 167 insertions(+), 119 deletions(-) diff --git a/src/mapgen/earth/osmium-inl.h b/src/mapgen/earth/osmium-inl.h index 6377367a8..41e288c3c 100644 --- a/src/mapgen/earth/osmium-inl.h +++ b/src/mapgen/earth/osmium-inl.h @@ -1,5 +1,6 @@ #include #include +#include #include #include "irr_v3d.h" #include "irrlichttypes.h" @@ -188,44 +189,51 @@ public: void way(const osmium::Way &way) { - arnis::Ground ground; - ground.mg = mg; - arnis::WorldEditor editor; - editor.mg = mg; - editor.ground = &ground; - std::vector v; - arnis::ProcessedWay w; - for (const auto &t : way.tags()) { - w.tags.emplace(t.key(), t.value()); + try { + arnis::Ground ground; + ground.mg = mg; + arnis::WorldEditor editor; + editor.mg = mg; + editor.ground = &ground; + std::vector v; + arnis::ProcessedWay w; + for (const auto &t : way.tags()) { + w.tags.emplace(t.key(), t.value()); + } + for (const auto &n : way.nodes()) { + arnis::ProcessedNode pn; + pn.tags = w.tags; + const auto [x, y] = editor.node_to_xz(n); + pn.x = x; + pn.z = y; + pn.id = w.id; + w.nodes.emplace_back(pn); + } + v.emplace_back(w); + arnis::generate_world(editor, v); + } catch (const std::exception &ex) { + DUMP(ex.what()); } - for (const auto &n : way.nodes()) { - arnis::ProcessedNode pn; - pn.tags = w.tags; - const auto [x, y] = editor.node_to_xz(n); - pn.x = x; - pn.z = y; - pn.id = w.id; - w.nodes.emplace_back(pn); - } - v.emplace_back(w); - arnis::generate_world(editor, v); } void relation(const osmium::Relation &relation) { - - arnis::Ground ground; - ground.mg = mg; - arnis::WorldEditor editor; - editor.mg = mg; - editor.ground = &ground; - std::vector v; - for (const auto &r : relation) { + try { + arnis::Ground ground; + ground.mg = mg; + arnis::WorldEditor editor; + editor.mg = mg; + editor.ground = &ground; + std::vector v; + for (const auto &r : relation) { + } + for (const auto &sn : relation.subitems()) { + way(sn); + } + arnis::generate_world(editor, v); + } catch (const std::exception &ex) { + DUMP(ex.what()); } - for (const auto &sn : relation.subitems()) { - way(sn); - } - arnis::generate_world(editor, v); } }; class hdl : public handler_i @@ -239,10 +247,7 @@ class hdl : public handler_i MyHandler handler; public: - hdl(MapgenEarth *mg, const std::string &path_name) : - path_name{path_name} - { - } + hdl(MapgenEarth *mg, const std::string &path_name) : path_name{path_name} {} ~hdl() = default; diff --git a/src/mapgen/mapgen_earth.cpp b/src/mapgen/mapgen_earth.cpp index 24192a84a..c9e936cf4 100644 --- a/src/mapgen/mapgen_earth.cpp +++ b/src/mapgen/mapgen_earth.cpp @@ -21,11 +21,13 @@ along with Freeminer. If not, see . #include #include +#include #include #include #include #include #include +#include #include "debug/dump.h" #include "emerge.h" @@ -354,111 +356,141 @@ const auto floor01 = [](const auto &v, const float &div) { return floor(v * div) //const auto ceil01 = [](const auto &v, const float &div) { return ceil(v * div) / div; }; -const auto make_bbox = [](auto tc, auto div) { - const auto lat_dec01 = floor01(tc.lat, div); - const auto lon_dec01 = floor01(tc.lon, div); - const auto lat_end_dec01 = floor01(tc.lat + (1.0 / div), div); - const auto lon_end_dec01 = floor01(tc.lon + (1.0 / div), div); +auto bbox_to_string(const auto &start, const auto &end) +{ std::stringstream bboxs; - bboxs << lon_dec01 << "," << lat_dec01 << "," << lon_end_dec01 << "," - << lat_end_dec01; - auto bbox = bboxs.str(); - return bbox; + bboxs << start.lon << "," << start.lat << "," << end.lon << "," << end.lat; + return bboxs.str(); +} + +auto make_bbox(const auto &tc, auto div) +{ + const ll start{floor01(tc.lat, div), floor01(tc.lon, div)}; + const ll end{floor01(tc.lat + (1.0 / div), div), floor01(tc.lon + (1.0 / div), div)}; + const auto bbox = bbox_to_string(start, end); + return std::make_tuple(bbox, start, end); }; void MapgenEarth::generateBuildings() { #if USE_OSMIUM + TimeTaker timer("earth buildings"); + std::string use_file; + try { - //#define FILE_INCLUDED 1 - //#include "earth/osmium-inl.h" - const auto tc = pos_to_ll(node_min.X, node_min.Z); - const auto tc_max = pos_to_ll(node_max.X, node_max.Z); - static const auto folder = porting::path_cache + DIR_DELIM + "earth"; - const auto lat_dec = lat_start(tc.lat); - const auto lon_dec = lon_start(tc.lon); + //#define FILE_INCLUDED 1 + //#include "earth/osmium-inl.h" + const auto tc = pos_to_ll(node_min.X, node_min.Z); + const auto tc_max = pos_to_ll(node_max.X, node_max.Z); + static const auto folder = porting::path_cache + DIR_DELIM + "earth"; + const auto lat_dec = lat_start(tc.lat); + const auto lon_dec = lon_start(tc.lon); - static const auto timestamp = []() { - std::string ts = "latest"; - g_settings->getNoEx("earth_movisda_timestamp", ts); - return ts; - }(); - char buff[100]; - std::snprintf(buff, sizeof(buff), "%c%02d%c%03d-%s.osm.pbf", lat_dec >= 0 ? 'N' : 'S', - abs(lat_dec), lon_dec >= 0 ? 'W' : 'E', abs(lon_dec), timestamp.c_str()); - std::string filename = buff; - const auto base_full_name = folder + DIR_DELIM + filename; - if (!std::filesystem::exists(base_full_name)) { - const auto lock = std::lock_guard(maps_holder->osm_http_lock); + static const auto timestamp = []() { + std::string ts = "latest"; + g_settings->getNoEx("earth_movisda_timestamp", ts); + return ts; + }(); + char buff[100]; + std::snprintf(buff, sizeof(buff), "%c%02d%c%03d-%s.osm.pbf", + lat_dec >= 0 ? 'N' : 'S', abs(lat_dec), lon_dec >= 0 ? 'W' : 'E', + abs(lon_dec), timestamp.c_str()); + std::string filename = buff; + const auto base_full_name = folder + DIR_DELIM + filename; if (!std::filesystem::exists(base_full_name)) { - const auto url = "https://osm.download.movisda.io/grid/" + filename; - multi_http_to_file({url}, base_full_name); + const auto lock = std::lock_guard(maps_holder->osm_http_lock); + if (!std::filesystem::exists(base_full_name)) { + const auto url = "https://osm.download.movisda.io/grid/" + filename; + multi_http_to_file({url}, base_full_name); + } } - } - std::string use_file = base_full_name; - std::string bbox; - { - const auto try_extract = [](const auto &path_name, const auto &bbox, - const auto &filename) { - if (std::filesystem::exists(filename)) { - return true; - } - const auto lock = std::lock_guard(maps_holder->osm_extract_lock); - if (std::filesystem::exists(filename)) { - return true; - } + use_file = base_full_name; + std::string bbox; + { + const auto try_extract = [](const auto &path_name, const auto &bbox, + const auto &filename) { + if (std::filesystem::exists(filename)) { + return true; + } + const auto lock = std::lock_guard(maps_holder->osm_extract_lock); + if (std::filesystem::exists(filename)) { + return true; + } - std::stringstream cmd; - // TODO: use osmium tool as lib - cmd << "osmium extract --output-format pbf --strategy smart " << "--bbox " - << bbox << " --output " << filename << ".tmp" << " " << path_name; - exec_to_string(cmd.str()); - if (!std::filesystem::exists(filename + ".tmp")) { - return false; - } + std::stringstream cmd; + // TODO: use osmium tool as lib + cmd << "osmium extract --output-format pbf --strategy smart " << "--bbox " + << bbox << " --output " << filename << ".tmp" << " " << path_name; + exec_to_string(cmd.str()); + if (!std::filesystem::exists(filename + ".tmp")) { + return false; + } - std::error_code error_code; - std::filesystem::rename(filename + ".tmp", filename, error_code); - return !error_code.value(); - }; - - for (auto div = 10; div <= 1000; div *= 10) { - std::error_code ec; - const auto size = std::filesystem::file_size(use_file, ec); - if (ec || size < 40000) { - break; + std::error_code error_code; + std::filesystem::rename(filename + ".tmp", filename, error_code); + return !error_code.value(); }; - const auto bbox_next = make_bbox(tc, div); - auto filename_next = folder + DIR_DELIM + "extract." + std::to_string(div) + - "." + bbox_next + ".osm.pbf"; - if (!try_extract(use_file, bbox_next, filename_next)) { - break; + for (auto div = 10; div <= 10000; div *= 10) { + std::error_code ec; + const auto size = std::filesystem::file_size(use_file, ec); + if (ec) { + break; + }; + + auto [bbox_next, bb_start, bb_end] = make_bbox(tc, div); + const auto bbox_to_filename = [](const auto &bbox_next, const auto div) { + auto filename_next = folder + DIR_DELIM + "extract." + + std::to_string(div) + "." + bbox_next + + ".osm.pbf"; + return filename_next; + }; + auto filename_next = bbox_to_filename(bbox_next, div); + + if (!(bb_start.lat <= tc.lat && bb_start.lon <= tc.lon && + bb_end.lat >= tc_max.lat && bb_end.lon >= tc_max.lon)) { + + const auto bbox_exact = bbox_to_string(tc, tc_max); + const auto filename_exact = bbox_to_filename(bbox_exact, 100000); + filename_next = filename_exact; + bbox_next = bbox_exact; + } + + if (!try_extract(use_file, bbox_next, filename_next)) { + break; + } + if (div >= 1000) { + maps_holder->files_to_delete.emplace_back(filename_next); + } + use_file = filename_next; + bbox = bbox_next; } - use_file = filename_next; - bbox = bbox_next; } - } - if (std::filesystem::exists(use_file)) { - const auto osm = std::make_shared(this, use_file); - const auto lock = maps_holder->osm_bbox.lock_unique_rec(); - if (!maps_holder->osm_bbox.contains(bbox)) { - maps_holder->osm_bbox.emplace(bbox, osm); + if (std::filesystem::exists(use_file) && std::filesystem::file_size(use_file)) { + if (!maps_holder->osm_bbox.contains(bbox)) { + const auto osm = std::make_shared(this, use_file); + const auto lock = maps_holder->osm_bbox.lock_unique_rec(); + if (!maps_holder->osm_bbox.contains(bbox)) { + maps_holder->osm_bbox.emplace(bbox, osm); + } + } } + + if (const auto &hdlr = maps_holder->osm_bbox.get(bbox)) { + hdlr->apply(this); + } + } catch (const std::exception &ex) { + warningstream << node_min << " : " << ex.what() << " file=" << use_file << "\n"; } - if (const auto &hdlr = maps_holder->osm_bbox.get(bbox)) { - hdlr->apply(this); - } - - verbosestream << "Buildings stat: " << node_min << " set=" << stat.set - << " miss=" << stat.miss << " level=" << stat.level - << " check=" << stat.check << " fill=" << stat.fill << "\n"; + verbosestream << "Buildings stat: " << node_min << " .. " << node_max + << " set=" << stat.set << " miss=" << stat.miss + << " level=" << stat.level << " check=" << stat.check + << " fill=" << stat.fill << " per=" << timer.getTimerTime() << "\n"; stat.clean(); - #endif } @@ -478,3 +510,11 @@ weather::humidity_t MapgenEarth::calcBlockHumidity(const v3pos_t &p, uint64_t se return m_emerge->biomemgr->calcBlockHumidity( p, seed, timeofday, totaltime, use_weather); } + +maps_holder_t::~maps_holder_t() +{ + for (const auto &file : files_to_delete) { + std::error_code ec; + std::filesystem::remove(file, ec); + } +}; \ No newline at end of file diff --git a/src/mapgen/mapgen_earth.h b/src/mapgen/mapgen_earth.h index eea5c204e..ca662b351 100644 --- a/src/mapgen/mapgen_earth.h +++ b/src/mapgen/mapgen_earth.h @@ -31,6 +31,7 @@ along with Freeminer. If not, see . #include "porting.h" #include "filesys.h" #include "threading/concurrent_map.h" +#include "threading/concurrent_vector.h" typedef core::vector2d v2d; @@ -65,7 +66,7 @@ class MapgenEarth; class handler_i { public: - virtual void apply(MapgenEarth*) = 0; + virtual void apply(MapgenEarth *) = 0; }; struct maps_holder_t @@ -76,6 +77,8 @@ struct maps_holder_t concurrent_shared_map osm_bbox; std::mutex osm_http_lock; std::mutex osm_extract_lock; + concurrent_shared_vector files_to_delete; + ~maps_holder_t(); }; class MapgenEarth : public MapgenV7 From ec0f04656fb2020e9a644556fc1b6710b8caae61 Mon Sep 17 00:00:00 2001 From: proller Date: Mon, 13 Oct 2025 04:08:40 +0200 Subject: [PATCH 11/36] farlights --- src/client/mapblock_mesh.cpp | 52 ++++++++++++++++++++++++++++++++++-- src/fm_server.cpp | 1 + src/fm_world_merge.cpp | 32 ++++++++++++++++++++-- src/fm_world_merge.h | 1 + src/mapblock.cpp | 34 +++++++++++++++++++++++ src/mapblock.h | 4 +++ 6 files changed, 120 insertions(+), 4 deletions(-) diff --git a/src/client/mapblock_mesh.cpp b/src/client/mapblock_mesh.cpp index 6298c1b82..a98faaaf2 100644 --- a/src/client/mapblock_mesh.cpp +++ b/src/client/mapblock_mesh.cpp @@ -32,7 +32,8 @@ MeshMakeData::MeshMakeData(const NodeDefManager *ndef, u16 side_length, MeshGrid mesh_grid - , int lod_step, int far_step, + , int lod_step + , int far_step, NodeContainer *nodecontainer) : m_side_length(side_length >> lod_step), m_mesh_grid(mesh_grid), @@ -42,7 +43,7 @@ MeshMakeData::MeshMakeData(const NodeDefManager *ndef, side_length_data{side_length}, lod_step{lod_step}, far_step{far_step}, - fscale(1<<(far_step + lod_step)) + fscale(1 << (far_step + lod_step)) { assert(m_side_length > 0); } @@ -742,6 +743,53 @@ MapBlockMesh::MapBlockMesh(Client *client, MeshMakeData *data): buf->drop(); } + if (static const auto farlights = g_settings->getBool("farlights"); farlights && far_step) { + scene::SMeshBuffer *buffer = new scene::SMeshBuffer(); + buffer->Material.PointCloud = true; + buffer->Material.BackfaceCulling = false; + buffer->Material.FogEnable = true; + v3bpos_t ofs; + const auto &storage = + client->getEnv().getClientMap().far_blocks_storage[far_step]; + int index_i = 0; + for (ofs.Z = 0; ofs.Z < mesh_grid.cell_size; ofs.Z++) { + for (ofs.Y = 0; ofs.Y < mesh_grid.cell_size; ofs.Y++) { + for (ofs.X = 0; ofs.X < mesh_grid.cell_size; ofs.X++) { + v3bpos_t p = (bp + ofs); // * MAP_BLOCKSIZE; + const auto block = storage.get(p).block; + + if (!block) + continue; + if (block->m_light_points.empty()) + continue; + const auto bpos_rel = block->getPosRelative(); + for (const auto &lp : block->m_light_points) { + if (++index_i > 16000) + break; + float r{200}; + float g{230}; + float b{static_cast(16 * lp.second)}; + const auto color_far_scale = far_step / 3.0f; + if (!color_far_scale) { + continue; + } + r /= color_far_scale; + g /= color_far_scale; + b /= color_far_scale; + const video::SColor c(255 / fscale, r, g, b); + const auto lpos_rel = lp.first - bpos_rel; + const auto coord = posToFloat(lpos_rel, BS); + video::S3DVertex v(coord.X, coord.Y, coord.Z, 0.0f, 0.0f, + 1.0f, c, 0.0f, 0.0f); + buffer->Vertices->Data.emplace_back(v); + buffer->Indices->Data.emplace_back(index_i); + } + } + } + } + mesh->addMeshBuffer(buffer); + } + if (mesh) { // Use VBO for mesh (this just would set this for every buffer) mesh->setHardwareMappingHint(scene::EHM_STATIC); diff --git a/src/fm_server.cpp b/src/fm_server.cpp index 1336ef0da..8dae9f86c 100644 --- a/src/fm_server.cpp +++ b/src/fm_server.cpp @@ -765,6 +765,7 @@ void *WorldMergeThread::run() merger.world_merge_max_clients = m_server->isSingleplayer() ? 1 : 0; g_settings->getU32NoEx("world_merge_max_clients", merger.world_merge_max_clients); g_settings->getU32NoEx("world_merge_lazy_up", merger.lazy_up); + g_settings->getBoolNoEx("farlights", merger.farlights); { merger.world_merge_load_all = -1; diff --git a/src/fm_world_merge.cpp b/src/fm_world_merge.cpp index 6b94d6b77..e6f0bc1a2 100644 --- a/src/fm_world_merge.cpp +++ b/src/fm_world_merge.cpp @@ -184,11 +184,17 @@ void WorldMerger::merge_one_block(MapDatabase *dbase, MapDatabase *dbase_up, top_c[c] += 4; } - if (const auto light_night = n.getLightRaw( - LIGHTBANK_NIGHT, ndef->getLightingFlags(n)); + const auto &lf = ndef->getLightingFlags(c); + if (const auto light_night = n.getLightRaw(LIGHTBANK_NIGHT, lf); light_night) { top_light_night.emplace_back(light_night); } + if (farlights && !step && (lf.light_source)) { + const auto plpos = + block->getPosRelative() + p; //pos_in_block; + const auto &[i, r] = block->m_light_points.try_emplace( + plpos, lf.light_source); + } nodes[c] = n; } @@ -221,6 +227,28 @@ void WorldMerger::merge_one_block(MapDatabase *dbase, MapDatabase *dbase_up, } // TODO: skip full air; + if (farlights) { + int lights_count = 0, lights_used = 0; + constexpr auto some_magick_thinner_const = 3; // more -> less far ligts + for (const auto &[bpos, block] : blocks) { + if (!block) { + continue; + } + // TODO: apply some smart? filtering here + block_up->m_light_points.insert( + block->m_light_points.begin(), block->m_light_points.end()); + for (const auto &lp : block->m_light_points) { + ++lights_count; + if (lights_count % (some_magick_thinner_const * (16 - lp.second))) { + continue; + } + ++lights_used; + block_up->m_light_points.emplace(lp); + } + + } + } + if (!not_empty_nodes) { return; } diff --git a/src/fm_world_merge.h b/src/fm_world_merge.h index 369bacba2..597f827ce 100644 --- a/src/fm_world_merge.h +++ b/src/fm_world_merge.h @@ -40,6 +40,7 @@ public: uint32_t world_merge_throttle{}; uint32_t world_merge_max_clients{}; int16_t world_merge_load_all{}; // -1 : auto; 0 : disable; 1 : force + bool farlights {true}; bool partial{}; uint32_t lazy_up{}; const NodeDefManager *const ndef{}; diff --git a/src/mapblock.cpp b/src/mapblock.cpp index 485fd6bb6..81c597b18 100644 --- a/src/mapblock.cpp +++ b/src/mapblock.cpp @@ -18,6 +18,7 @@ #include "content_mapnode.h" // For legacy name-id mapping #include "content_nodemeta.h" // For legacy deserialization #include "serialization.h" +#include "util/msgpack_serialize.h" #if CHECK_CLIENT_BUILD() #include "client/mapblock_mesh.h" #endif @@ -243,6 +244,12 @@ MapNode MapBlock::getNodeTry(const v3pos_t &p) return getNodeNoLock(p); } +constexpr auto MAPBLOCK_DATA{0}; +enum +{ + MAPBLOCK_LIGHT_POINTS +}; + // == /* @@ -539,7 +546,12 @@ void MapBlock::serialize(std::ostream &os_compressed, u8 version, bool disk, int infostream<<" serialize not generated block"<= 27) { @@ -627,6 +639,14 @@ void MapBlock::serialize(std::ostream &os_compressed, u8 version, bool disk, int } } + // freeminer + if (flags & (1 << 7)) { + MSGPACK_PACKET_INIT((int)MAPBLOCK_DATA, 1); + PACK(MAPBLOCK_LIGHT_POINTS, m_light_points); + os_raw << serializeString32(std::string_view{buffer.data(), buffer.size()}); + } + // ========= + if (version >= 29) { // now compress the whole thing compress(os_raw.str(), os_compressed, version, compression_level); @@ -805,6 +825,20 @@ bool MapBlock::deSerialize(std::istream &in_compressed, u8 version, bool disk) analyzeContent(); } + if (flags & (1 << 7)) { + std::string data = deSerializeString32(is); + if (!data.empty()) { + msgpack::unpacked msg; + msgpack::unpack(msg, data.data(), data.size()); + auto &obj = msg.get(); + auto packet = obj.as(); + const auto it = packet.find(MAPBLOCK_LIGHT_POINTS); + if (it != packet.end()) { + it->second.convert(m_light_points); + } + } + } + TRACESTREAM(<<"MapBlock::deSerialize "< +#include +#include #include #include "fm_nodecontainer.h" #include "irr_v3d.h" @@ -536,6 +538,8 @@ public: std::mutex abm_triggers_mutex; size_t abmTriggersRun(ServerEnvironment *m_env, u32 time, uint8_t activate = 0); uint32_t m_abm_timestamp{}; + using light_t = uint8_t; + std::unordered_map m_light_points; u32 getActualTimestamp() { From 7bccc57b15fe0744d2dae7895c57a599d741dd45 Mon Sep 17 00:00:00 2001 From: proller Date: Mon, 13 Oct 2025 04:20:32 +0200 Subject: [PATCH 12/36] farlights --- src/defaultsettings.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/defaultsettings.cpp b/src/defaultsettings.cpp index 49563bc33..226d98cd0 100644 --- a/src/defaultsettings.cpp +++ b/src/defaultsettings.cpp @@ -158,6 +158,7 @@ void fm_set_default_settings(Settings *settings) { settings->setDefault("farmesh_stable", "0"); settings->setDefault("farmesh_server", "1"); settings->setDefault("farmesh_all_changed", slow ? "1000" : "10000"); + settings->setDefault("farlights", "1"); settings->setDefault("headless_optimize", "false"); //settings->setDefault("node_highlighting", "halo"); From 367a7dae3482d0b753bffb5aa65c4fb1fafbe94f Mon Sep 17 00:00:00 2001 From: proller Date: Mon, 13 Oct 2025 15:42:51 +0200 Subject: [PATCH 13/36] farlights --- src/fm_world_merge.cpp | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/src/fm_world_merge.cpp b/src/fm_world_merge.cpp index e6f0bc1a2..e9d19eeec 100644 --- a/src/fm_world_merge.cpp +++ b/src/fm_world_merge.cpp @@ -228,21 +228,26 @@ void WorldMerger::merge_one_block(MapDatabase *dbase, MapDatabase *dbase_up, // TODO: skip full air; if (farlights) { - int lights_count = 0, lights_used = 0; - constexpr auto some_magick_thinner_const = 3; // more -> less far ligts + size_t lights_count = 0; + // size_t lights_used = 0; + constexpr auto some_magick_thinner_const = 2; // more -> less far ligts + constexpr auto min_no_skip_ligts = + 2; // do not skip this amount lights on block << farstep for (const auto &[bpos, block] : blocks) { if (!block) { continue; } + size_t lights_in_block = 0; // TODO: apply some smart? filtering here - block_up->m_light_points.insert( - block->m_light_points.begin(), block->m_light_points.end()); + // block_up->m_light_points.insert(block->m_light_points.begin(), block->m_light_points.end()); for (const auto &lp : block->m_light_points) { ++lights_count; - if (lights_count % (some_magick_thinner_const * (16 - lp.second))) { + ++lights_in_block; + if (lights_in_block > (min_no_skip_ligts << step) && + (lights_count % (some_magick_thinner_const * (16 - lp.second)))) { continue; } - ++lights_used; + //++lights_used; block_up->m_light_points.emplace(lp); } @@ -252,6 +257,7 @@ void WorldMerger::merge_one_block(MapDatabase *dbase, MapDatabase *dbase_up, if (!not_empty_nodes) { return; } + block_up->setGenerated(true); ServerMap::saveBlock(block_up.get(), dbase_up, m_map_compression_level); } From 38d9bb58826592acd66ec80a4756542eb15f4490 Mon Sep 17 00:00:00 2001 From: proller Date: Mon, 13 Oct 2025 23:42:53 +0200 Subject: [PATCH 14/36] earth --- src/emerge.cpp | 6 +++--- src/fm_world_merge.cpp | 1 - src/mapgen/earth/hgt.cpp | 40 ++++++++++++++++++----------------- src/mapgen/earth/http.cpp | 4 ++-- src/mapgen/earth/osmium-inl.h | 8 +++---- src/servermap.cpp | 3 ++- util/autotest/auto.pl | 3 ++- 7 files changed, 34 insertions(+), 31 deletions(-) diff --git a/src/emerge.cpp b/src/emerge.cpp index e819ead84..47d607d58 100644 --- a/src/emerge.cpp +++ b/src/emerge.cpp @@ -642,7 +642,7 @@ MapBlock *EmergeThread::finishGen(v3s16 pos, BlockMakeData *bmdata, m_map->finishBlockMake(bmdata, modified_blocks, m_server->m_env->getGameTime()); - MapBlock *block = m_map->getBlockNoCreateNoEx(pos, false, true); + MapBlockPtr block = m_map->getBlock(pos, false, true); if (!block) { errorstream << "EmergeThread::finishGen: Couldn't grab block we " "just generated: " << pos << std::endl; @@ -671,7 +671,7 @@ MapBlock *EmergeThread::finishGen(v3s16 pos, BlockMakeData *bmdata, m_server->setAsyncFatalError(e); } - EMERGE_DBG_OUT("ended up with: " << analyze_block(block)); + EMERGE_DBG_OUT("ended up with: " << analyze_block(block.get())); /* Clear mapgen state @@ -680,7 +680,7 @@ MapBlock *EmergeThread::finishGen(v3s16 pos, BlockMakeData *bmdata, m_mapgen->gennotify.clearEvents(); // m_mapgen->vm = nullptr; - return block; + return block.get(); } diff --git a/src/fm_world_merge.cpp b/src/fm_world_merge.cpp index e9d19eeec..3401d2f54 100644 --- a/src/fm_world_merge.cpp +++ b/src/fm_world_merge.cpp @@ -250,7 +250,6 @@ void WorldMerger::merge_one_block(MapDatabase *dbase, MapDatabase *dbase_up, //++lights_used; block_up->m_light_points.emplace(lp); } - } } diff --git a/src/mapgen/earth/hgt.cpp b/src/mapgen/earth/hgt.cpp index 3c25d2f5e..6f93e6acd 100644 --- a/src/mapgen/earth/hgt.cpp +++ b/src/mapgen/earth/hgt.cpp @@ -65,16 +65,18 @@ height::height_t hgts::get(height_hgt::ll_t lat, height_hgt::ll_t lon) const auto lat1 = height::lat_start(lat); // + 90 % 180; const auto lon1 = height::lon_start(lon); + { + const auto &map1_lat1 = map1[lat1]; + if (const auto it = map1_lat1.find(lon1); it != map1_lat1.end()) { + prev_layer_height = it->second->get(lat, lon); - if (map1[lat1].contains(lon1)) { - prev_layer_height = map1[lat1][lon1]->get(lat, lon); - - if constexpr (layers) { - if (prev_layer_height) { + if constexpr (layers) { + if (prev_layer_height) { + return prev_layer_height; + } + } else { return prev_layer_height; } - } else { - return prev_layer_height; } } @@ -90,8 +92,11 @@ height::height_t hgts::get(height_hgt::ll_t lat, height_hgt::ll_t lon) //DUMP((long)this, "notfound, will load", lat, lon, lat1, lon1, lat90, lon90, map1[lat1].contains(lon1), prev_layer_height); const auto lock = std::unique_lock(mutex); - if (map1[lat1].contains(lon1)) { - prev_layer_height = map1[lat1][lon1]->get(lat, lon); + const auto &map1_lat1 = map1[lat1]; + + if (const auto it = map1_lat1.find(lon1); it != map1_lat1.end()) { + prev_layer_height = it->second->get(lat, lon); + if constexpr (layers) { if (prev_layer_height) { return prev_layer_height; @@ -123,15 +128,15 @@ height::height_t hgts::get(height_hgt::ll_t lat, height_hgt::ll_t lon) }; if (lat <= 90 && lat >= -90 && lon <= 180 && lon >= -180) { - // DUMP("insert", (long)this, lat, lon, folder, map1.size(), map1[lat1].size()); - if (!map1[lat1].contains(lon1)) { + // DUMP("insert", (long)this, lat, lon, folder, map1.size(), map1_lat1.size()); + if (!map1_lat1.contains(lon1)) { auto hgt = std::make_shared(folder, lat, lon); const int lat_dec = hgt->lat_start(lat); const int lon_dec = hgt->lon_start(lon); if (hgt->load(lat, lon)) { map1[lat_dec][lon_dec] = std::move(hgt); prev_layer_height = map1[lat_dec][lon_dec]->get(lat, lon); - DUMP("hgt ok", lat, lon, lat_dec, lon_dec, prev_layer_height); + //DUMP("hgt ok", lat, lon, lat_dec, lon_dec, prev_layer_height); if constexpr (layers) { if (prev_layer_height) { @@ -181,7 +186,7 @@ height::height_t hgts::get(height_hgt::ll_t lat, height_hgt::ll_t lon) } } if (!map90[lat90].contains(lon90)) { - place_dummy90(lat90, lon90); + return place_dummy90(lat90, lon90); } return map90[lat90][lon90]->get(lat, lon); } @@ -259,8 +264,7 @@ bool height_hgt::load(ll_t lat, ll_t lon) //DUMP(lat_dec, lon_dec); return false; } - DUMP((long long)this, lat_dec, lon_dec, lat_loading, lon_loading, lat_loaded, - lon_loaded); + //DUMP((long long)this, lat_dec, lon_dec, lat_loading, lon_loading, lat_loaded, lon_loaded); TimeTaker timer("hgt load"); lat_loading = lat_dec; @@ -459,9 +463,7 @@ bool height_hgt::load(ll_t lat, ll_t lon) } lat_loaded = lat_dec; lon_loaded = lon_dec; - DUMP("loadok", (long long)this, heights.size(), lat_loaded, lon_loaded, filesize, - zipname, filename, seconds_per_px_x, get(lat_dec, lon_dec), heights[0], - heights.back(), heights[side_length_x]); + //DUMP("loadok", (long long)this, heights.size(), lat_loaded, lon_loaded, filesize, zipname, filename, seconds_per_px_x, get(lat_dec, lon_dec), heights[0], heights.back(), heights[side_length_x]); return true; } @@ -968,7 +970,7 @@ height::height_t height::get(ll_t lat, ll_t lon) //lat_seconds, lon_seconds, seconds_per_px_x, seconds_per_px_y, lat, lon, lat_loaded, lon_loaded, (lat - lat_loaded), pixel_per_deg_x, (lon - lon_loaded), pixel_per_deg_y); - //return height[2]; // debug not interpolated + //return height[2]; // debug not interpolated #endif // ratio where X lays diff --git a/src/mapgen/earth/http.cpp b/src/mapgen/earth/http.cpp index e9fa837b9..cae01271a 100644 --- a/src/mapgen/earth/http.cpp +++ b/src/mapgen/earth/http.cpp @@ -70,7 +70,7 @@ size_t multi_http_to_file(const std::string &name, const std::vector &links, const std::stri http_failed.emplace(path); - warningstream + infostream << "Not found " << path << "\n" << "try to download manually: \n" << "curl -o " << path << " " diff --git a/src/mapgen/earth/osmium-inl.h b/src/mapgen/earth/osmium-inl.h index 41e288c3c..83001bc70 100644 --- a/src/mapgen/earth/osmium-inl.h +++ b/src/mapgen/earth/osmium-inl.h @@ -244,8 +244,6 @@ class hdl : public handler_i const std::string path_name; - MyHandler handler; - public: hdl(MapgenEarth *mg, const std::string &path_name) : path_name{path_name} {} @@ -275,10 +273,12 @@ public: } arnis::init(mg); + + MyHandler handler; + handler.mg = mg; osmium::apply(reader, cache, handler, - mp_manager.handler([&handler = this->handler]( - const osmium::memory::Buffer &area_buffer) { + mp_manager.handler([&handler](const osmium::memory::Buffer &area_buffer) { osmium::apply(area_buffer, handler); })); } diff --git a/src/servermap.cpp b/src/servermap.cpp index 1aabcdcc4..7f7385cc0 100644 --- a/src/servermap.cpp +++ b/src/servermap.cpp @@ -321,7 +321,8 @@ void ServerMap::finishBlockMake(BlockMakeData *data, } for (auto &changed_block : *changed_blocks) { - MapBlock *block = changed_block.second; + const auto block = getBlock(changed_block.first); // very bad, changed_block should contain MapBlockPtr + //MapBlock *block = changed_block.second; if (!block) continue; /* diff --git a/util/autotest/auto.pl b/util/autotest/auto.pl index bf2bb3485..ba045d976 100755 --- a/util/autotest/auto.pl +++ b/util/autotest/auto.pl @@ -83,7 +83,8 @@ $0 ----world_sand $0 -mg_name=earth -mg_earth='{"center":{"z":36.822183, "y":0, "x":30.583390}}' bot #$0 -mg_name=earth -mg_earth='{"scale":{"z":10000, "y":0.01, "x":10000}}' bot $0 -mg_name=earth -mg_earth='{"scale":{"z":10000, "y":100, "x":10000}}' bot -$0 -mg_name=earth -mg_earth='{"center":{"z":27.9878279,"y":0,"x":86.923833}}' -static_spawnpoint='(130,8842,56)' bot # everest +$0 -mg_name=earth -mg_earth='{"center":{"z":27.9878279,"y":0,"x":86.923833}}' -static_spawnpoint='(130,8842,56)' bot # Everest +$0 -mg_name=earth -mg_earth='{"center":{"z":22.28422,"x":114.15996,"y":0} }' bot # HongKong $0 ---cmake_minetest=1 ---build_name=_minetest ----headless ----headless_optimize --address=cool.server.org --port=30001 ---clients_num=25 clients From 3843520d33c9dff4929ccdb46cbf83e9c7386a81 Mon Sep 17 00:00:00 2001 From: proller Date: Mon, 13 Oct 2025 23:43:41 +0200 Subject: [PATCH 15/36] farlights --- src/client/clientmap.cpp | 5 ++++- src/client/mapblock_mesh.cpp | 3 +++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/client/clientmap.cpp b/src/client/clientmap.cpp index 874bc7752..2754939da 100644 --- a/src/client/clientmap.cpp +++ b/src/client/clientmap.cpp @@ -1373,11 +1373,14 @@ static u32 transformBuffersToDrawOrder( new_buffer = true; else if (tmp->getVertexCount() + buf->getVertexCount() > U16_MAX) new_buffer = true; + else if (tmp->getPrimitiveType() != buf->getPrimitiveType()) + new_buffer = true; if (new_buffer) { finish_buf(); tmp = new scene::SMeshBuffer(); + tmp->setPrimitiveType(buf->getPrimitiveType()); put_buffers.buf.push_back(tmp); - assert(tmp->getPrimitiveType() == buf->getPrimitiveType()); + //assert(tmp->getPrimitiveType() == buf->getPrimitiveType()); tmp->Material = buf->getMaterial(); // preallocate approximately tmp->Vertices->Data.reserve(MYMIN(U16_MAX, total_vtx)); diff --git a/src/client/mapblock_mesh.cpp b/src/client/mapblock_mesh.cpp index a98faaaf2..23cfdb1a6 100644 --- a/src/client/mapblock_mesh.cpp +++ b/src/client/mapblock_mesh.cpp @@ -4,6 +4,7 @@ #include "mapblock_mesh.h" #include "CMeshBuffer.h" +#include "EPrimitiveTypes.h" #include "client.h" #include "client/clientmap.h" #include "mapblock.h" @@ -745,6 +746,7 @@ MapBlockMesh::MapBlockMesh(Client *client, MeshMakeData *data): 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; buffer->Material.BackfaceCulling = false; buffer->Material.FogEnable = true; @@ -788,6 +790,7 @@ MapBlockMesh::MapBlockMesh(Client *client, MeshMakeData *data): } } mesh->addMeshBuffer(buffer); + buffer->drop(); } if (mesh) { From 31daddf46330ea4e5b406e916aabedf3efd7a259 Mon Sep 17 00:00:00 2001 From: proller Date: Tue, 14 Oct 2025 02:07:54 +0200 Subject: [PATCH 16/36] fix --- games/default | 2 +- src/fm_world_merge.cpp | 5 ++++- src/mapgen/mapgen.h | 5 +++-- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/games/default b/games/default index af6935757..d99b96e65 160000 --- a/games/default +++ b/games/default @@ -1 +1 @@ -Subproject commit af693575799508aa672c9679b9639af4df772051 +Subproject commit d99b96e652d9a3ef1a53b230ec351cb8bfb57b1d diff --git a/src/fm_world_merge.cpp b/src/fm_world_merge.cpp index 3401d2f54..8551740fd 100644 --- a/src/fm_world_merge.cpp +++ b/src/fm_world_merge.cpp @@ -185,11 +185,14 @@ void WorldMerger::merge_one_block(MapDatabase *dbase, MapDatabase *dbase_up, } const auto &lf = ndef->getLightingFlags(c); + const auto &cf = ndef->get(c); + if (const auto light_night = n.getLightRaw(LIGHTBANK_NIGHT, lf); light_night) { top_light_night.emplace_back(light_night); } - if (farlights && !step && (lf.light_source)) { + // TODO: whats with lava? + if (farlights && !step && (lf.light_source) && !cf.isLiquid()) { const auto plpos = block->getPosRelative() + p; //pos_in_block; const auto &[i, r] = block->m_light_points.try_emplace( diff --git a/src/mapgen/mapgen.h b/src/mapgen/mapgen.h index 0a5fba6c3..8238eba40 100644 --- a/src/mapgen/mapgen.h +++ b/src/mapgen/mapgen.h @@ -103,10 +103,11 @@ private: // Order must match the order of 'static MapgenDesc g_reg_mapgens[]' in mapgen.cpp enum MapgenType { + // freeminer: MAPGEN_EARTH, - MAPGEN_INDEV, MAPGEN_MATH, - + MAPGEN_INDEV, + // ========== MAPGEN_V7, MAPGEN_VALLEYS, From 02eac66b4477deab34a858468e4afd46bde02491 Mon Sep 17 00:00:00 2001 From: proller Date: Tue, 14 Oct 2025 02:23:07 +0200 Subject: [PATCH 17/36] lights --- src/client/fm_client.cpp | 13 ++++++++----- src/fm_world_merge.cpp | 31 +++++++++++++++---------------- src/fm_world_merge.h | 11 ++++++++--- 3 files changed, 31 insertions(+), 24 deletions(-) diff --git a/src/client/fm_client.cpp b/src/client/fm_client.cpp index ec9f46c5e..504b65add 100644 --- a/src/client/fm_client.cpp +++ b/src/client/fm_client.cpp @@ -3,23 +3,26 @@ #include #include #include "client.h" -#include "fm_far_calc.h" #include "client/mapblock_mesh.h" #include "clientmap.h" #include "emerge.h" +#include "filesys.h" +#include "fm_far_calc.h" #include "fm_weather.h" #include "fm_world_merge.h" #include "irr_v3d.h" #include "log.h" -#include "mapblock.h" -#include "network/fm_networkprotocol.h" -#include "server.h" -#include "filesys.h" #include "map.h" +#include "mapblock.h" #include "mapgen/mapgen.h" +#include "network/fm_networkprotocol.h" #include "network/networkpacket.h" +#include "server.h" #include "threading/lock.h" #include "util/directiontables.h" +#include +#include +#include void Client::updateMeshTimestampWithEdge(const v3bpos_t &blockpos) { diff --git a/src/fm_world_merge.cpp b/src/fm_world_merge.cpp index 8551740fd..dd27dd5f3 100644 --- a/src/fm_world_merge.cpp +++ b/src/fm_world_merge.cpp @@ -66,8 +66,8 @@ WorldMerger::~WorldMerger() merge_changed(); } -void WorldMerger::merge_one_block(MapDatabase *dbase, MapDatabase *dbase_up, - const v3bpos_t &bpos_aligned, block_step_t step) +WorldMerger::one_block_stat_t WorldMerger::merge_one_block(MapDatabase *dbase, + MapDatabase *dbase_up, const v3bpos_t &bpos_aligned, block_step_t step) { const auto step_pow = 1; const auto step_size = 1 << step_pow; @@ -111,7 +111,7 @@ void WorldMerger::merge_one_block(MapDatabase *dbase, MapDatabase *dbase_up, // actionstream << "s=" << step <<" at=" << block_up->getActualTimestamp() << " t=" << block_up->getTimestamp() << " myts=" << timestamp << "\n"; const auto up_ts = block_up->getActualTimestamp(); if (timestamp < up_ts + lazy_up) { - return; + return {}; } } } @@ -229,10 +229,8 @@ void WorldMerger::merge_one_block(MapDatabase *dbase, MapDatabase *dbase_up, } } // TODO: skip full air; - + one_block_stat_t one_step_stat; if (farlights) { - size_t lights_count = 0; - // size_t lights_used = 0; constexpr auto some_magick_thinner_const = 2; // more -> less far ligts constexpr auto min_no_skip_ligts = 2; // do not skip this amount lights on block << farstep @@ -244,24 +242,25 @@ void WorldMerger::merge_one_block(MapDatabase *dbase, MapDatabase *dbase_up, // TODO: apply some smart? filtering here // block_up->m_light_points.insert(block->m_light_points.begin(), block->m_light_points.end()); for (const auto &lp : block->m_light_points) { - ++lights_count; + ++one_step_stat.lights_count; ++lights_in_block; if (lights_in_block > (min_no_skip_ligts << step) && - (lights_count % (some_magick_thinner_const * (16 - lp.second)))) { + (one_step_stat.lights_count % + (some_magick_thinner_const * (16 - lp.second)))) { continue; } - //++lights_used; + ++one_step_stat.lights_used; block_up->m_light_points.emplace(lp); } } } - if (!not_empty_nodes) { - return; + if (not_empty_nodes) { + block_up->setGenerated(true); + ServerMap::saveBlock(block_up.get(), dbase_up, m_map_compression_level); } - block_up->setGenerated(true); - ServerMap::saveBlock(block_up.get(), dbase_up, m_map_compression_level); + return one_step_stat; } bool WorldMerger::merge_one_step( @@ -300,7 +299,7 @@ bool WorldMerger::merge_one_step( size_t processed = 0; const auto time_start = porting::getTimeMs(); - + WorldMerger::one_block_stat_t statz; const auto printstat = [&]() { const auto time = porting::getTimeMs(); @@ -310,6 +309,7 @@ bool WorldMerger::merge_one_step( << blocks_size //<< " blocks loaded " << m_server->getMap().m_blocks.size() << " processed " << processed << " per " << (time - time_start) / 1000 + << " lights" << statz.lights_used << "/" << statz.lights_count << " speed " << processed / (((time - time_start) / 1000) ?: 1) << '\n'; }; @@ -337,8 +337,7 @@ bool WorldMerger::merge_one_step( g_profiler->add("Server: World merge blocks", 1); try { - - merge_one_block(dbase_current, dbase_up, bpos_aligned, step); + statz = merge_one_block(dbase_current, dbase_up, bpos_aligned, step); if (!(cur_n % 10000)) { printstat(); diff --git a/src/fm_world_merge.h b/src/fm_world_merge.h index 597f827ce..a2aa20676 100644 --- a/src/fm_world_merge.h +++ b/src/fm_world_merge.h @@ -40,7 +40,7 @@ public: uint32_t world_merge_throttle{}; uint32_t world_merge_max_clients{}; int16_t world_merge_load_all{}; // -1 : auto; 0 : disable; 1 : force - bool farlights {true}; + bool farlights{true}; bool partial{}; uint32_t lazy_up{}; const NodeDefManager *const ndef{}; @@ -56,9 +56,14 @@ public: bool stop(); bool throttle(); - void merge_one_block(MapDatabase *dbase, MapDatabase *dbase_up, - const v3bpos_t &bpos_aligned, block_step_t step); + struct one_block_stat_t + { + size_t lights_count{}; + size_t lights_used{}; + }; + one_block_stat_t merge_one_block(MapDatabase *dbase, MapDatabase *dbase_up, + const v3bpos_t &bpos_aligned, block_step_t step); bool merge_one_step(block_step_t step, std::unordered_set &blocks_todo); bool merge_list(std::unordered_set &blocks_todo); bool merge_all(); From 453b461450cb11068d546a38b96008f6c2538acb Mon Sep 17 00:00:00 2001 From: proller Date: Tue, 14 Oct 2025 04:44:09 +0000 Subject: [PATCH 18/36] earth --- src/mapgen/mapgen_earth.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mapgen/mapgen_earth.cpp b/src/mapgen/mapgen_earth.cpp index c9e936cf4..012b5c977 100644 --- a/src/mapgen/mapgen_earth.cpp +++ b/src/mapgen/mapgen_earth.cpp @@ -394,7 +394,7 @@ void MapgenEarth::generateBuildings() }(); char buff[100]; std::snprintf(buff, sizeof(buff), "%c%02d%c%03d-%s.osm.pbf", - lat_dec >= 0 ? 'N' : 'S', abs(lat_dec), lon_dec >= 0 ? 'W' : 'E', + lat_dec >= 0 ? 'N' : 'S', abs(lat_dec), lon_dec > 0 ? 'W' : 'E', abs(lon_dec), timestamp.c_str()); std::string filename = buff; const auto base_full_name = folder + DIR_DELIM + filename; From 4cfe4aa1e817d66bce7b50664cf07a3e862f582a Mon Sep 17 00:00:00 2001 From: proller Date: Tue, 14 Oct 2025 02:23:07 +0200 Subject: [PATCH 19/36] lights --- src/fm_world_merge.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/fm_world_merge.cpp b/src/fm_world_merge.cpp index dd27dd5f3..b706679cd 100644 --- a/src/fm_world_merge.cpp +++ b/src/fm_world_merge.cpp @@ -299,7 +299,7 @@ bool WorldMerger::merge_one_step( size_t processed = 0; const auto time_start = porting::getTimeMs(); - WorldMerger::one_block_stat_t statz; + WorldMerger::one_block_stat_t stat_step; const auto printstat = [&]() { const auto time = porting::getTimeMs(); @@ -309,7 +309,7 @@ bool WorldMerger::merge_one_step( << blocks_size //<< " blocks loaded " << m_server->getMap().m_blocks.size() << " processed " << processed << " per " << (time - time_start) / 1000 - << " lights" << statz.lights_used << "/" << statz.lights_count + << " lights " << stat_step.lights_used << "/" << stat_step.lights_count << " speed " << processed / (((time - time_start) / 1000) ?: 1) << '\n'; }; @@ -337,7 +337,10 @@ bool WorldMerger::merge_one_step( g_profiler->add("Server: World merge blocks", 1); try { - statz = merge_one_block(dbase_current, dbase_up, bpos_aligned, step); + const auto stat_block = + merge_one_block(dbase_current, dbase_up, bpos_aligned, step); + stat_step.lights_count += stat_block.lights_count; + stat_step.lights_used += stat_block.lights_used; if (!(cur_n % 10000)) { printstat(); From 9b9044fcc4b28703645303cfefc0fa9966d7609c Mon Sep 17 00:00:00 2001 From: proller Date: Thu, 16 Oct 2025 04:14:10 +0200 Subject: [PATCH 20/36] wip --- src/client/mapblock_mesh.cpp | 2 +- src/mapgen/earth/arnis_adapter.cpp | 1 + src/mapgen/earth/arnis_adapter.h | 2 + src/mapgen/mapgen_earth.cpp | 49 +++-- src/mapgen/mapgen_earth.h | 5 +- src/util/lrucache.hpp | 279 +++++++++++++++++++++++++++++ util/autotest/auto.pl | 2 +- 7 files changed, 319 insertions(+), 21 deletions(-) create mode 100644 src/util/lrucache.hpp diff --git a/src/client/mapblock_mesh.cpp b/src/client/mapblock_mesh.cpp index 23cfdb1a6..8dbd72776 100644 --- a/src/client/mapblock_mesh.cpp +++ b/src/client/mapblock_mesh.cpp @@ -778,7 +778,7 @@ MapBlockMesh::MapBlockMesh(Client *client, MeshMakeData *data): r /= color_far_scale; g /= color_far_scale; b /= color_far_scale; - const video::SColor c(255 / fscale, r, g, b); + const video::SColor c(0 / fscale, r, g, b); const auto lpos_rel = lp.first - bpos_rel; const auto coord = posToFloat(lpos_rel, BS); video::S3DVertex v(coord.X, coord.Y, coord.Z, 0.0f, 0.0f, diff --git a/src/mapgen/earth/arnis_adapter.cpp b/src/mapgen/earth/arnis_adapter.cpp index 4dbdddac2..a7e3e5f40 100644 --- a/src/mapgen/earth/arnis_adapter.cpp +++ b/src/mapgen/earth/arnis_adapter.cpp @@ -6,4 +6,5 @@ XZ::operator XZPoint() { return XZPoint{X, Y}; } +const std::vector ProcessedElement::dummy_nodes; } \ No newline at end of file diff --git a/src/mapgen/earth/arnis_adapter.h b/src/mapgen/earth/arnis_adapter.h index b1a5a1cbb..47d11a98a 100644 --- a/src/mapgen/earth/arnis_adapter.h +++ b/src/mapgen/earth/arnis_adapter.h @@ -172,10 +172,12 @@ public: } } + const static std::vector dummy_nodes; const std::vector &nodes() const { if (is_way()) return as_way().nodes; + return dummy_nodes; } static ProcessedElement FromNode(const ProcessedNode &n) diff --git a/src/mapgen/mapgen_earth.cpp b/src/mapgen/mapgen_earth.cpp index 012b5c977..ded1c076b 100644 --- a/src/mapgen/mapgen_earth.cpp +++ b/src/mapgen/mapgen_earth.cpp @@ -29,6 +29,7 @@ along with Freeminer. If not, see . #include #include +#include "constants.h" #include "debug/dump.h" #include "emerge.h" #include "filesys.h" @@ -47,6 +48,7 @@ along with Freeminer. If not, see . #include "nodedef.h" #include "serverenvironment.h" #include "settings.h" +#include "util/timetaker.h" #include "voxel.h" #include "voxelalgorithms.h" #if USE_OSMIUM @@ -65,6 +67,7 @@ along with Freeminer. If not, see . #include #include #endif + std::unique_ptr MapgenEarth::maps_holder; void MapgenEarthParams::setDefaultSettings(Settings *settings) @@ -138,7 +141,7 @@ MapgenEarth::MapgenEarth(MapgenEarthParams *params_, EmergeParams *emerge) : // mg_params = (MapgenEarthParams *)params_->sparams; mg_params = params_; - Json::Value ¶ms = mg_params->params; + const Json::Value ¶ms = mg_params->params; flags = 0; if (params.get("light", 0).asBool()) @@ -216,8 +219,9 @@ MapgenEarth::~MapgenEarth() MapNode MapgenEarth::layers_get(float value, float max) { - auto layer_index = rangelim((unsigned int)myround((value / max) * layers_node_size), - 0, layers_node_size - 1); + const auto layer_index = + rangelim((unsigned int)myround((value / max) * layers_node_size), 0, + layers_node_size - 1); return layers_node[layer_index]; } @@ -273,7 +277,7 @@ v2pos_t MapgenEarth::ll_to_pos(const ll &l) pos_t MapgenEarth::get_height(pos_t x, pos_t z) { const auto tc = pos_to_ll(x, z); - auto y = maps_holder->hgt_reader.get(tc.lat, tc.lon); + const auto y = maps_holder->hgt_reader.get(tc.lat, tc.lon); return ceil(y / scale.Y) - center.Y; } @@ -289,18 +293,18 @@ int MapgenEarth::getGroundLevelAtPoint(v2pos_t p) int MapgenEarth::generateTerrain() { - MapNode n_ice(c_ice); + const MapNode n_ice(c_ice); u32 index = 0; - auto em = vm->m_area.getExtent(); + const auto em = vm->m_area.getExtent(); for (pos_t z = node_min.Z; z <= node_max.Z; z++) { for (pos_t x = node_min.X; x <= node_max.X; x++, index++) { - auto heat = + const auto heat = m_emerge->env->m_use_weather ? m_emerge->env->getServerMap().updateBlockHeat(m_emerge->env, v3pos_t(x, node_max.Y, z), nullptr, &heat_cache) : 0; - auto height = get_height(x, z); + const auto height = get_height(x, z); u32 i = vm->m_area.index(x, node_min.Y, z); for (pos_t y = node_min.Y; y <= node_max.Y; y++) { bool underground = height >= y; @@ -375,7 +379,7 @@ void MapgenEarth::generateBuildings() { #if USE_OSMIUM - TimeTaker timer("earth buildings"); + TimeTaker timer("earth buildings", {}, PRECISION_MILLI); std::string use_file; try { @@ -396,7 +400,7 @@ void MapgenEarth::generateBuildings() std::snprintf(buff, sizeof(buff), "%c%02d%c%03d-%s.osm.pbf", lat_dec >= 0 ? 'N' : 'S', abs(lat_dec), lon_dec > 0 ? 'W' : 'E', abs(lon_dec), timestamp.c_str()); - std::string filename = buff; + const std::string filename = buff; const auto base_full_name = folder + DIR_DELIM + filename; if (!std::filesystem::exists(base_full_name)) { const auto lock = std::lock_guard(maps_holder->osm_http_lock); @@ -421,8 +425,10 @@ void MapgenEarth::generateBuildings() std::stringstream cmd; // TODO: use osmium tool as lib - cmd << "osmium extract --output-format pbf --strategy smart " << "--bbox " - << bbox << " --output " << filename << ".tmp" << " " << path_name; + // --option types=multipolygon,route + cmd << "osmium extract --output-format pbf --strategy smart --option types=any " + << "--bbox " << bbox << " --output " << filename << ".tmp" << " " + << path_name; exec_to_string(cmd.str()); if (!std::filesystem::exists(filename + ".tmp")) { return false; @@ -461,35 +467,42 @@ void MapgenEarth::generateBuildings() if (!try_extract(use_file, bbox_next, filename_next)) { break; } + if (div >= 1000) { maps_holder->files_to_delete.emplace_back(filename_next); } + use_file = filename_next; bbox = bbox_next; } } if (std::filesystem::exists(use_file) && std::filesystem::file_size(use_file)) { + const auto lock = std::lock_guard{maps_holder->osm_bbox_lock}; if (!maps_holder->osm_bbox.contains(bbox)) { const auto osm = std::make_shared(this, use_file); - const auto lock = maps_holder->osm_bbox.lock_unique_rec(); + //const auto lock = maps_holder->osm_bbox.lock_unique_rec(); if (!maps_holder->osm_bbox.contains(bbox)) { maps_holder->osm_bbox.emplace(bbox, osm); } } } - if (const auto &hdlr = maps_holder->osm_bbox.get(bbox)) { - hdlr->apply(this); + { + const auto lock = std::lock_guard{maps_holder->osm_bbox_lock}; + if (const auto &hdlr = maps_holder->osm_bbox.get(bbox)) { + hdlr.value()->apply(this); + } } } catch (const std::exception &ex) { warningstream << node_min << " : " << ex.what() << " file=" << use_file << "\n"; } - verbosestream << "Buildings stat: " << node_min << " .. " << node_max + verbosestream << "Buildings stat: " << node_min << " .. " << node_max << " " << " set=" << stat.set << " miss=" << stat.miss << " level=" << stat.level << " check=" << stat.check - << " fill=" << stat.fill << " per=" << timer.getTimerTime() << "\n"; + << " fill=" << stat.fill << " per=" << timer.getTimerTime() + << " mh=" << maps_holder->osm_bbox.size() << "\n"; stat.clean(); #endif } @@ -514,7 +527,9 @@ weather::humidity_t MapgenEarth::calcBlockHumidity(const v3pos_t &p, uint64_t se maps_holder_t::~maps_holder_t() { for (const auto &file : files_to_delete) { +#if NDEBUG std::error_code ec; std::filesystem::remove(file, ec); +#endif } }; \ No newline at end of file diff --git a/src/mapgen/mapgen_earth.h b/src/mapgen/mapgen_earth.h index ca662b351..a39985534 100644 --- a/src/mapgen/mapgen_earth.h +++ b/src/mapgen/mapgen_earth.h @@ -32,6 +32,7 @@ along with Freeminer. If not, see . #include "filesys.h" #include "threading/concurrent_map.h" #include "threading/concurrent_vector.h" +#include "util/lrucache.hpp" typedef core::vector2d v2d; @@ -73,8 +74,8 @@ struct maps_holder_t { hgts hgt_reader{porting::path_cache + DIR_DELIM + "earth"}; using osm_ptr = std::shared_ptr; - concurrent_shared_map osm_by_path; - concurrent_shared_map osm_bbox; + lru_cache osm_bbox; + std::mutex osm_bbox_lock; std::mutex osm_http_lock; std::mutex osm_extract_lock; concurrent_shared_vector files_to_delete; diff --git a/src/util/lrucache.hpp b/src/util/lrucache.hpp new file mode 100644 index 000000000..b149c86a8 --- /dev/null +++ b/src/util/lrucache.hpp @@ -0,0 +1,279 @@ +// https://github.com/Guiorgy/cpp-lru-cache/blob/std-only/include/lrucache.hpp +/* +** File: lrucache.hpp +** +** Author: Alexander Ponomarev +** Created on June 20, 2013, 5:09 PM +** +** Author: Guiorgy +** Forked on October 23, 2024 +*/ + +#pragma once + +#include +#include +#include +#include +#include +#include + +// A helper macro that determines whether a specific attribute is supported by the current compiler. If __has_cpp_attribute is not defined, __cplusplus alone is used as a fallback. +#ifdef __has_cpp_attribute + #define GUIORGY_ATTRIBUTE_AVAILABLE(attribute_token, test_value, cpp_version) \ + (__has_cpp_attribute(attribute_token) >= test_value && __cplusplus >= cpp_version) +#else + #define GUIORGY_ATTRIBUTE_AVAILABLE(attribute_token, test_value, cpp_version) \ + (__cplusplus >= cpp_version) +#endif + +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wunknown-warning-option" +#pragma clang diagnostic ignored "-Wreserved-attribute-identifier" +#endif +#if !GUIORGY_ATTRIBUTE_AVAILABLE(nodiscard, 201907L, 202002L) + #ifdef nodiscard + #define GUIORGY_nodiscard_BEFORE + #undef nodiscard + #endif + #define nodiscard(explanation) nodiscard +#endif +#ifdef __clang__ +#pragma clang diagnostic pop +#endif + +template +class lru_cache final { + static_assert(max_size > 0); + + typedef typename std::pair key_value_pair_t; + typedef typename std::list::iterator list_iterator_t; + typedef typename std::list::reverse_iterator list_reverse_iterator_t; + typedef typename std::unordered_map::iterator map_iterator_t; + +public: + typedef typename std::list::const_iterator iterator; + typedef typename std::list::const_iterator const_iterator; + typedef typename std::list::const_reverse_iterator reverse_iterator; + typedef typename std::list::const_reverse_iterator const_reverse_iterator; + +private: + std::list _cache_items_list; + std::unordered_map _cache_items_map; + +public: + lru_cache() = default; + ~lru_cache() = default; + lru_cache(const lru_cache& other) { + _cache_items_list = other._cache_items_list; + + _cache_items_map.reserve(_cache_items_list.size()); + for (list_iterator_t it = _cache_items_list.begin(); it != _cache_items_list.end(); ++it) { + _cache_items_map.emplace_hint(_cache_items_map.end(), it->first, it); + } + } + lru_cache(lru_cache&&) = default; + lru_cache& operator=(lru_cache const& other) { + _cache_items_list = other._cache_items_list; + + _cache_items_map.reserve(_cache_items_list.size()); + for (list_iterator_t it = _cache_items_list.begin(); it != _cache_items_list.end(); ++it) { + _cache_items_map.emplace_hint(_cache_items_map.end(), it->first, it); + } + + return *this; + } + lru_cache& operator=(lru_cache &&) = default; + +private: + void put(const key_t& key) { + map_iterator_t it = _cache_items_map.find(key); + + if (it != _cache_items_map.end()) { + _cache_items_list.erase(it->second); + it->second = _cache_items_list.begin(); + } else { + _cache_items_map.emplace_hint(it, key, _cache_items_list.begin()); + } + + if (_cache_items_map.size() > max_size) { + list_reverse_iterator_t last = _cache_items_list.rbegin(); + _cache_items_map.erase(last->first); + _cache_items_list.pop_back(); + } + } + +public: + void put(const key_t& key, const value_t& value) { + _cache_items_list.emplace_front(key, value); + put(key); + } + + void put(const key_t& key, value_t&& value) { + _cache_items_list.emplace_front(key, std::move(value)); + put(key); + } + + template + const value_t& emplace(const key_t& key, ValueArgs&&... value_args) { + const value_t& value = _cache_items_list.emplace_front( + std::piecewise_construct, + std::forward_as_tuple(key), + std::forward_as_tuple(std::forward(value_args)...) + ).second; + put(key); + return value; + } + + [[nodiscard("Use touch(const key_t& key) instead if all you want is to push the key to the bottom of the removal order")]] const std::optional get(const key_t& key) { + map_iterator_t it = _cache_items_map.find(key); + + if (it == _cache_items_map.end()) { + return std::nullopt; + } else { + if (it->second != _cache_items_list.begin()) { + _cache_items_list.splice(_cache_items_list.begin(), _cache_items_list, it->second); + } + return it->second->second; + } + } + + [[nodiscard("Use touch(const key_t& key) instead if all you want is to push the key to the bottom of the removal order")]] const std::optional> get_ref(const key_t& key) { + map_iterator_t it = _cache_items_map.find(key); + + if (it == _cache_items_map.end()) { + return std::nullopt; + } else { + if (it->second != _cache_items_list.begin()) { + _cache_items_list.splice(_cache_items_list.begin(), _cache_items_list, it->second); + } + return std::make_optional(std::cref(it->second->second)); + } + } + + [[nodiscard("Use touch(const key_t& key) instead if all you want is to push the key to the bottom of the removal order")]] bool try_get(const key_t& key, value_t& value_out) { + map_iterator_t it = _cache_items_map.find(key); + + if (it == _cache_items_map.end()) { + return false; + } else { + if (it->second != _cache_items_list.begin()) { + _cache_items_list.splice(_cache_items_list.begin(), _cache_items_list, it->second); + } + value_out = it->second->second; + return true; + } + } + + [[nodiscard("Use touch(const key_t& key) instead if all you want is to push the key to the bottom of the removal order")]] bool try_get_ref(const key_t& key, const value_t*& value_out) { + map_iterator_t it = _cache_items_map.find(key); + + if (it == _cache_items_map.end()) { + value_out = nullptr; + return false; + } else { + if (it->second != _cache_items_list.begin()) { + _cache_items_list.splice(_cache_items_list.begin(), _cache_items_list, it->second); + } + value_out = &(it->second->second); + return true; + } + } + + bool touch(const key_t& key) { + map_iterator_t it = _cache_items_map.find(key); + + if (it == _cache_items_map.end()) { + return false; + } else { + if (it->second != _cache_items_list.begin()) { + _cache_items_list.splice(_cache_items_list.begin(), _cache_items_list, it->second); + } + return true; + } + } + + bool remove(const key_t& key) { + map_iterator_t it = _cache_items_map.find(key); + + if (it != _cache_items_map.end()) { + _cache_items_list.erase(it->second); + _cache_items_map.erase(it); + return true; + } else { + return false; + } + } + + [[nodiscard]] bool exists(const key_t& key) const { + return _cache_items_map.find(key) != _cache_items_map.end(); + } + + [[nodiscard]] bool contains(const key_t& key) const { + return _cache_items_map.find(key) != _cache_items_map.end(); + } + + [[nodiscard]] std::size_t size() const noexcept { + return _cache_items_map.size(); + } + + void clear() noexcept { + _cache_items_map.clear(); + _cache_items_list.clear(); + } + + [[nodiscard]] const_iterator cbegin() const noexcept { + return _cache_items_list.cbegin(); + } + + [[nodiscard]] const_iterator begin() const noexcept { + return cbegin(); + } + + [[nodiscard]] const_iterator cend() const noexcept { + return _cache_items_list.cend(); + } + + [[nodiscard]] const_iterator end() const noexcept { + return cend(); + } + + [[nodiscard]] const_reverse_iterator crbegin() const noexcept { + return _cache_items_list.crbegin(); + } + + [[nodiscard]] const_iterator rbegin() const noexcept { + return crbegin(); + } + + [[nodiscard]] const_reverse_iterator crend() const noexcept { + return _cache_items_list.crend(); + } + + [[nodiscard]] const_iterator rend() const noexcept { + return crend(); + } +}; + +// Restore nodiscard if it was already defined, otherwise undefine it +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wunknown-warning-option" +#pragma clang diagnostic ignored "-Wreserved-attribute-identifier" +#endif +#ifdef GUIORGY_nodiscard_BEFORE + #undef nodiscard + #define nodiscard GUIORGY_nodiscard_BEFORE + #undef GUIORGY_nodiscard_BEFORE +#else + #ifdef nodiscard + #undef nodiscard + #endif +#endif +#ifdef __clang__ +#pragma clang diagnostic pop +#endif + +// Cleanup of internal macros. +#undef GUIORGY_ATTRIBUTE_AVAILABLE diff --git a/util/autotest/auto.pl b/util/autotest/auto.pl index ba045d976..b541b1175 100755 --- a/util/autotest/auto.pl +++ b/util/autotest/auto.pl @@ -414,7 +414,7 @@ $commands = { file_append( "$config->{logdir}/run.sh", join "\n", - qq{# } . join(' ', $0, map { /[\s"]/ ? "'" . $_ . "'" : $_ } @ARGV), + qq{# } . join(' ', $0, map { /[()\s"]/ ? "'" . $_ . "'" : $_ } @ARGV), qq{cd "$build_dir"}, "" ); From ab0c172ff66751efe88845aa8913a71f2c14a0b5 Mon Sep 17 00:00:00 2001 From: proller Date: Thu, 16 Oct 2025 04:19:03 +0200 Subject: [PATCH 21/36] lights --- src/fm_world_merge.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/fm_world_merge.cpp b/src/fm_world_merge.cpp index b706679cd..ff6123a80 100644 --- a/src/fm_world_merge.cpp +++ b/src/fm_world_merge.cpp @@ -244,7 +244,7 @@ WorldMerger::one_block_stat_t WorldMerger::merge_one_block(MapDatabase *dbase, for (const auto &lp : block->m_light_points) { ++one_step_stat.lights_count; ++lights_in_block; - if (lights_in_block > (min_no_skip_ligts << step) && + if ((step > 3 || lights_in_block > (min_no_skip_ligts << step)) && (one_step_stat.lights_count % (some_magick_thinner_const * (16 - lp.second)))) { continue; From 8c88649601cb07c52cd1d8b7573206f9afa98796 Mon Sep 17 00:00:00 2001 From: proller Date: Fri, 17 Oct 2025 00:08:50 +0200 Subject: [PATCH 22/36] wip --- src/server.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/server.cpp b/src/server.cpp index ec24f6331..b8e454ebc 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -1511,6 +1511,9 @@ void Server::yieldToOtherThreads(float dtime) PlayerSAO *Server::StageTwoClientInit(session_t peer_id) { + uint16_t net_proto_version_fm{}; + std::string full_version; + std::string playername; std::unique_ptr sao; { @@ -1519,6 +1522,8 @@ PlayerSAO *Server::StageTwoClientInit(session_t peer_id) if (client) { playername = client->getName(); sao = emergePlayer(playername.c_str(), peer_id, client->net_proto_version); + net_proto_version_fm = client->net_proto_version_fm; + full_version = client->getFullVer(); } } @@ -1584,7 +1589,9 @@ PlayerSAO *Server::StageTwoClientInit(session_t peer_id) std::string ip_str = getPeerAddress(player->getPeerId()).serializeString(); const auto &names = m_clients.getPlayerNames(); - actionstream << player->getName() << " [" << ip_str << "] (" << player->protocol_version << ") joins game. List of players: "; + actionstream << player->getName() << " [" << ip_str << "] (" + << player->protocol_version << " : " << net_proto_version_fm << " : " + << full_version << ") joins game. List of players: "; for (const std::string &name : names) actionstream << name << " "; actionstream << player->getName() << std::endl; From 75bd731402f1e3ce09b75b8f0ccbf917cfc643e9 Mon Sep 17 00:00:00 2001 From: proller Date: Fri, 17 Oct 2025 04:52:55 +0200 Subject: [PATCH 23/36] up --- cmake/Modules/freeminer_src.cmake | 3 +-- src/mapgen/earth/arnis-cpp | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/cmake/Modules/freeminer_src.cmake b/cmake/Modules/freeminer_src.cmake index 2626489f2..022ad3a6d 100644 --- a/cmake/Modules/freeminer_src.cmake +++ b/cmake/Modules/freeminer_src.cmake @@ -175,8 +175,7 @@ if (USE_DEBUG_DUMP) if (CMAKE_BUILD_TYPE STREQUAL "Debug") add_definitions(-DDUMP_STREAM=actionstream) else() - #add_definitions(-DDUMP_STREAM=verbosestream) - add_definitions(-DDUMP_STREAM=actionstream) + add_definitions(-DDUMP_STREAM=verbosestream) endif() endif () diff --git a/src/mapgen/earth/arnis-cpp b/src/mapgen/earth/arnis-cpp index 7f1cba84a..a514e6b9f 160000 --- a/src/mapgen/earth/arnis-cpp +++ b/src/mapgen/earth/arnis-cpp @@ -1 +1 @@ -Subproject commit 7f1cba84aa53fa708fe19a3bdbc4155b7261345d +Subproject commit a514e6b9ff8e0aeae263248c50703f0c58bfe145 From f3af1bd2bc07d276e3e7b7ebf37c04808a946eb9 Mon Sep 17 00:00:00 2001 From: proller Date: Mon, 20 Oct 2025 04:54:46 +0200 Subject: [PATCH 24/36] earth weather --- src/mapgen/earth/png_holder.h | 181 ++++++++++++++++++++++++++++++++++ src/mapgen/earth/rgb_temp.h | 116 ++++++++++++++++++++++ src/mapgen/mapgen_earth.cpp | 39 +++++++- src/mapgen/mapgen_earth.h | 3 + src/mapgen/mg_biome.cpp | 30 ++++-- 5 files changed, 358 insertions(+), 11 deletions(-) create mode 100644 src/mapgen/earth/png_holder.h create mode 100644 src/mapgen/earth/rgb_temp.h diff --git a/src/mapgen/earth/png_holder.h b/src/mapgen/earth/png_holder.h new file mode 100644 index 000000000..34de4aeee --- /dev/null +++ b/src/mapgen/earth/png_holder.h @@ -0,0 +1,181 @@ +#pragma once + +#include +#include +#include +#include +#include +#include +#include +//#include +#include "SColor.h" + +//struct RGBA {uint8_t r, g, b, a;}; +using RGBA = video::SColor; + +class PngImage { +public: + // open and read PNG, convert to 8-bit RGBA + explicit PngImage(const std::string& filename) { + fp_ = std::fopen(filename.c_str(), "rb"); + if (!fp_) throw std::runtime_error("Failed to open file: " + filename); + + png_ptr_ = png_create_read_struct(PNG_LIBPNG_VER_STRING, nullptr, nullptr, nullptr); + if (!png_ptr_) { + std::fclose(fp_); + fp_ = nullptr; + throw std::runtime_error("png_create_read_struct failed"); + } + + info_ptr_ = png_create_info_struct(png_ptr_); + if (!info_ptr_) { + png_destroy_read_struct(&png_ptr_, nullptr, nullptr); + std::fclose(fp_); + fp_ = nullptr; + throw std::runtime_error("png_create_info_struct failed"); + } + + if (setjmp(png_jmpbuf(png_ptr_))) { + // libpng error + cleanup(); + throw std::runtime_error("libpng error during init/read"); + } + + png_init_io(png_ptr_, fp_); + png_read_info(png_ptr_, info_ptr_); + + png_uint_32 w, h; + int bit_depth, color_type, interlace_type, compression_type, filter_method; + png_get_IHDR(png_ptr_, info_ptr_, &w, &h, &bit_depth, &color_type, + &interlace_type, &compression_type, &filter_method); + + width_ = static_cast(w); + height_ = static_cast(h); + + // Transformations to 8-bit RGBA: + // Expand palette, grayscale < 8, and tRNS to RGB(A) + png_set_expand(png_ptr_); + + // Convert 16-bit to 8-bit + if (bit_depth == 16) png_set_strip_16(png_ptr_); + + // Convert gray/gray+alpha to RGB(A) + if (color_type == PNG_COLOR_TYPE_GRAY || color_type == PNG_COLOR_TYPE_GRAY_ALPHA) + png_set_gray_to_rgb(png_ptr_); + + // Ensure we have alpha: if image has no alpha, add an opaque alpha channel + if (!(color_type & PNG_COLOR_MASK_ALPHA)) { + // Put alpha after RGB (i.e., RGBA) + png_set_filler(png_ptr_, 0xFF, PNG_FILLER_AFTER); + } + + // Handle interlace + png_set_interlace_handling(png_ptr_); + + // Update info after transformations + png_read_update_info(png_ptr_, info_ptr_); + + // Get bytes per row (after transforms) + png_uint_32 rowbytes = png_get_rowbytes(png_ptr_, info_ptr_); + if (rowbytes == 0) { + cleanup(); + throw std::runtime_error("Invalid rowbytes"); + } + + rowbytes_ = static_cast(rowbytes); + // allocate one contiguous buffer for all image data + image_data_.resize(rowbytes_ * static_cast(height_)); + row_pointers_.resize(height_); + + for (int i = 0; i < height_; ++i) { + row_pointers_[i] = image_data_.data() + (size_t)i * rowbytes_; + } + + // Read the image into our buffer + png_read_image(png_ptr_, row_pointers_.data()); + + // After read, we expect 4 bytes per pixel (RGBA) + // But verify: rowbytes must be width * 4 (or at least enough) + if (rowbytes_ < static_cast(width_) * 4) { + cleanup(); + throw std::runtime_error("Unexpected row size after transformation"); + } + } + + // Disable copy + PngImage(const PngImage&) = delete; + PngImage& operator=(const PngImage&) = delete; + + // Enable move + PngImage(PngImage&& other) noexcept { + steal_from(std::move(other)); + } + PngImage& operator=(PngImage&& other) noexcept { + if (this != &other) { + cleanup(); + steal_from(std::move(other)); + } + return *this; + } + + ~PngImage() { + cleanup(); + } + + int width() const noexcept { return width_; } + int height() const noexcept { return height_; } + + // Return RGBA for given coords, or std::nullopt if out of bounds. + std::optional get_pixel(int x, int y) const noexcept { + if (x < 0 || y < 0 || x >= width_ || y >= height_) return std::nullopt; + const uint8_t* row = row_pointers_[y]; + const uint8_t* px = row + static_cast(x) * 4; // 4 bytes per pixel (R,G,B,A) + RGBA c{ px[3], px[0], px[1], px[2] }; + return c; + } + +private: + png_structp png_ptr_ = nullptr; + png_infop info_ptr_ = nullptr; + FILE* fp_ = nullptr; + + int width_ = 0; + int height_ = 0; + size_t rowbytes_ = 0; + + std::vector image_data_; + std::vector row_pointers_; + + void cleanup() noexcept { + if (png_ptr_ || info_ptr_) { + // png_destroy_read_struct frees info_ptr_ as well + png_destroy_read_struct(&png_ptr_, &info_ptr_, nullptr); + png_ptr_ = nullptr; + info_ptr_ = nullptr; + } + if (fp_) { + std::fclose(fp_); + fp_ = nullptr; + } + image_data_.clear(); + row_pointers_.clear(); + } + + void steal_from(PngImage&& other) noexcept { + png_ptr_ = other.png_ptr_; + info_ptr_ = other.info_ptr_; + fp_ = other.fp_; + width_ = other.width_; + height_ = other.height_; + rowbytes_ = other.rowbytes_; + image_data_ = std::move(other.image_data_); + row_pointers_ = std::move(other.row_pointers_); + + other.png_ptr_ = nullptr; + other.info_ptr_ = nullptr; + other.fp_ = nullptr; + other.width_ = other.height_ = 0; + other.rowbytes_ = 0; + } +}; + diff --git a/src/mapgen/earth/rgb_temp.h b/src/mapgen/earth/rgb_temp.h new file mode 100644 index 000000000..ece1a0531 --- /dev/null +++ b/src/mapgen/earth/rgb_temp.h @@ -0,0 +1,116 @@ +// write function on c++ : params color in rgb encoding temperature from blue to red and returns temperature in celsius + +/* +I'm considering how to solve for inverse mapping by finding the parameter \( t \) that minimizes error. A brute-force search over the range [0, 1] with small steps or Newton's method could work, but implementing a numerical search sounds more robust. I can sample 1,000 points and refine via binary search for better matching. I’ll provide both a straightforward linear method and a more intricate jet inverse approach using C++17 with relevant examples. I’ll format everything in markdown!**Coding RGB to Temperature Conversion** + +I’m writing code that includes the `cmath` and `algorithm` libraries. First, I’ll define a function, `rgbToTemperatureLinear`, that converts RGB values to a temperature range based on given minimum and maximum temperatures. I’ll also implement `rgbToTemperatureJet`, which uses formulas to calculate values for red, green, and blue based on a temperature parameter \( t \). Next, I’ll execute a coarse search with 2,000 samples to find the best \( t \), and refine that with smaller steps to minimize the squared error.**Refining the Temperature Mapping** + +Next, I plan to refine the search around the best \( t \) value found earlier by using either the golden-section method or a simpler approach with a loop from 0 to 5. I’ll search within the range defined by \( t_{\text{best}} \) plus and minus a small delta, using a finer step of \( K = 200 \) to compute any necessary updates. As I decrease the delta for convergence, I'll ensure the final result is clear: returning the calculated temperature. + +I'll also include usage examples and note important considerations like potential ambiguities in mapping and the presence of noise.Below are two C++ functions you can use to convert an RGB color (assumed to encode a temperature on a blue→red scale) back to a temperature in Celsius. + +- The first function (rgbToCelsiusLinear) assumes a simple linear gradient from pure blue (0,0,255) at the cold end to pure red (255,0,0) at the hot end. It is cheap and analytic. +- The second function (rgbToCelsiusJet) handles a common “rainbow/jet-like” thermal map (blue→cyan→green→yellow→red) by numerically inverting the forward jet colormap. This is a more realistic thermal palette but requires sampling/search so it’s a bit heavier. + +Both functions take r,g,b in 0..255 and minTemp/maxTemp in Celsius (defaults given) and return a double temperature in Celsius. + +Code (C++17): +*/ +#pragma once +#include +#include +#include +#include + +// clamp helper +static inline double clamp01(double x) { + return std::max(0.0, std::min(1.0, x)); +} + +// 1) Simple linear blue->red gradient inversion +// Maps: blue (0,0,255) -> t=0 ; red (255,0,0) -> t=1 +// r,g,b are 0..255, returns temperature in Celsius between minTemp and maxTemp. +double rgbToCelsiusLinear(int r, int g, int b, double minTemp = -30.0, double maxTemp = 50.0) { + double rn = clamp01(r / 255.0); + double bn = clamp01(b / 255.0); + + // projection onto the R<-B gradient: t = (r_norm - b_norm + 1) / 2 + double t = (rn - bn + 1.0) / 2.0; + t = clamp01(t); + + return minTemp + t * (maxTemp - minTemp); +} + +// 2) Invert a typical "jet" / rainbow colormap numerically. +// Forward jet mapping (t in [0,1]) used here: +// r = clamp(1.5 - |4t - 3|) +// g = clamp(1.5 - |4t - 2|) +// b = clamp(1.5 - |4t - 1|) +static inline std::array jetColor(double t) { + t = clamp01(t); + double r = clamp01(1.5 - std::fabs(4.0 * t - 3.0)); + double g = clamp01(1.5 - std::fabs(4.0 * t - 2.0)); + double b = clamp01(1.5 - std::fabs(4.0 * t - 1.0)); + return {r, g, b}; +} + +// invert jet colormap by coarse-to-fine search +double rgbToCelsiusJet(int r, int g, int b, double minTemp = -30.0, double maxTemp = 50.0) { + const double rn = clamp01(r / 255.0); + const double gn = clamp01(g / 255.0); + const double bn = clamp01(b / 255.0); + + // coarse sampling to get initial guess + int coarseN = 800; // coarse samples (adjust for speed/precision) + double bestT = 0.0; + double bestErr = std::numeric_limits::infinity(); + + for (int i = 0; i < coarseN; ++i) { + double t = double(i) / double(coarseN - 1); + auto c = jetColor(t); + double err = (c[0] - rn)*(c[0] - rn) + (c[1] - gn)*(c[1] - gn) + (c[2] - bn)*(c[2] - bn); + if (err < bestErr) { + bestErr = err; + bestT = t; + } + } + + // refine around bestT with a few finer searches + double delta = 1.0 / double(coarseN - 1); + for (int pass = 0; pass < 4; ++pass) { + double start = clamp01(bestT - delta); + double end = clamp01(bestT + delta); + int fineN = 200; + double localBestT = bestT; + double localBestErr = bestErr; + for (int i = 0; i < fineN; ++i) { + double t = start + (end - start) * double(i) / double(fineN - 1); + auto c = jetColor(t); + double err = (c[0] - rn)*(c[0] - rn) + (c[1] - gn)*(c[1] - gn) + (c[2] - bn)*(c[2] - bn); + if (err < localBestErr) { + localBestErr = err; + localBestT = t; + } + } + bestT = localBestT; + bestErr = localBestErr; + delta *= 0.25; // shrink search radius + } + + double temp = minTemp + bestT * (maxTemp - minTemp); + return temp; +} + +/* +Usage examples: +- If your color map is exactly linear blue->red use rgbToCelsiusLinear. +- If your color map is a rainbow/thermal (blue→cyan→green→yellow→red) use rgbToCelsiusJet. + +Notes and caveats: +- The mapping from color to temperature is not unique without knowing the exact colormap and the numeric temperature range. You must supply the min and max temperatures that correspond to the cold and hot ends of the colormap. +- Real images may contain noise, gamma correction or encoding differences; you may need to pre-correct for gamma or color-space conversions if colors appear non-linear. +- If your colormap is different, provide its forward mapping and invert it similarly (analytic or numeric search). +- If you expect many conversions, precompute a lookup table (LUT) from colors to temperatures for speed. + +If you tell me which exact colormap and numeric temperature range you use (and whether input is linear RGB or sRGB), I can tailor the function exactly to that mapping. +*/ \ No newline at end of file diff --git a/src/mapgen/mapgen_earth.cpp b/src/mapgen/mapgen_earth.cpp index ded1c076b..c4f85ab0f 100644 --- a/src/mapgen/mapgen_earth.cpp +++ b/src/mapgen/mapgen_earth.cpp @@ -32,6 +32,9 @@ along with Freeminer. If not, see . #include "constants.h" #include "debug/dump.h" #include "emerge.h" +#include "mapgen/earth/png_holder.h" +#include "mapgen/earth/rgb_temp.h" +#include "server.h" #include "filesys.h" #include "irr_v2d.h" #include "irr_v3d.h" @@ -206,6 +209,14 @@ MapgenEarth::MapgenEarth(MapgenEarthParams *params_, EmergeParams *emerge) : hgt_reader.debug = 0; */ + { + const auto heat_img = m_emerge->env->m_server->getGameSpec()->path + "/" + + "mods/earth/data/earth_heat.png"; + if (std::filesystem::exists(heat_img)) { + heat_image = std::make_unique(heat_img); + } + } + if (!maps_holder) { maps_holder = std::make_unique(); } @@ -507,16 +518,42 @@ void MapgenEarth::generateBuildings() #endif } +/* +Heat data: +https://search.earthdata.nasa.gov/search/granules?p=C1276812859-GES_DISC&pg[0][v]=f&pg[0][gsk]=-start_date&g=G3503129918-GES_DISC&ff=Map%20Imagery&tl=1038183927.842!5!!&fsm0=Clouds&fst0=Atmosphere&long=2.3696682464454994&zoom=2.8910241901494977 +https://gibs-a.earthdata.nasa.gov/wmts/epsg4326/best/wmts.cgi?TIME=2025-03-01&layer=MERRA2_2m_Air_Temperature_Monthly&style=default&tilematrixset=2km&Service=WMTS&Request=GetTile&Version=1.0.0&Format=image%2Fpng&TileMatrix=0&TileCol=0&TileRow=0 + +Snow data: +https://cmr.earthdata.nasa.gov/search/concepts/C3050353608-NSIDC_CPRD.html +https://gibs-a.earthdata.nasa.gov/wmts/epsg4326/best/wmts.cgi?TIME=2025-03-01&layer=MODIS_Terra_L3_Snow_Cover_Monthly_Average_Pct&style=default&tilematrixset=2km&Service=WMTS&Request=GetTile&Version=1.0.0&Format=image%2Fpng&TileMatrix=0&TileCol=0&TileRow=0 +*/ + weather::heat_t MapgenEarth::calcBlockHeat(const v3pos_t &p, uint64_t seed, float timeofday, float totaltime, bool use_weather) { #if USE_OSMIUM const auto ll = pos_to_ll(p); - const auto tile = osmium::geom::Tile(3, osmium::Location(ll.lon, ll.lat)); + if (heat_image) { + const auto x = heat_image->width() * ((ll.lon + 180) / 360); + const auto y = (std::min( heat_image->height(), heat_image->width()/1.6 )) * ((ll.lat + 90) / 180); + const auto pixel = heat_image->get_pixel(x, y); + auto heat = rgbToCelsiusJet(pixel->getRed(), pixel->getGreen(), pixel->getBlue()); + heat += m_emerge->biomemgr->weather_heat_daily * + (sin(cycle_shift(timeofday, -0.25) * M_PI) - 0.5); //-64..0..34 + heat += p.Y / m_emerge->biomemgr->weather_heat_height; + if (m_emerge->biomemgr->weather_hot_core && + p.Y < -(WEATHER_LIMIT - m_emerge->biomemgr->weather_hot_core)) + heat += 6000 * + (1.0 - ((float)(p.Y - -WEATHER_LIMIT) / + m_emerge->biomemgr + ->weather_hot_core)); //hot core, later via realms + return heat; + } #endif return m_emerge->biomemgr->calcBlockHeat(p, seed, timeofday, totaltime, use_weather); } +// TODO: use cloud data weather::humidity_t MapgenEarth::calcBlockHumidity(const v3pos_t &p, uint64_t seed, float timeofday, float totaltime, bool use_weather) { diff --git a/src/mapgen/mapgen_earth.h b/src/mapgen/mapgen_earth.h index a39985534..e740fed40 100644 --- a/src/mapgen/mapgen_earth.h +++ b/src/mapgen/mapgen_earth.h @@ -34,6 +34,8 @@ along with Freeminer. If not, see . #include "threading/concurrent_vector.h" #include "util/lrucache.hpp" +class PngImage; + typedef core::vector2d v2d; //using ll_t = float; @@ -117,6 +119,7 @@ public: float totaltime, bool use_weather) override; weather::humidity_t calcBlockHumidity(const v3pos_t &p, uint64_t seed, float timeofday, float totaltime, bool use_weather) override; + std::unique_ptr heat_image; struct Stat { diff --git a/src/mapgen/mg_biome.cpp b/src/mapgen/mg_biome.cpp index 3aa8e7792..d2c080138 100644 --- a/src/mapgen/mg_biome.cpp +++ b/src/mapgen/mg_biome.cpp @@ -307,36 +307,45 @@ Biome *BiomeGenOriginal::calcBiomeFromNoise(float heat, float humidity, v3s16 po } // Freeminer Weather -weather::heat_t BiomeManager::calcBlockHeat(const v3pos_t &p, uint64_t seed, float timeofday, float totaltime, bool use_weather) { +weather::heat_t BiomeManager::calcBlockHeat(const v3pos_t &p, uint64_t seed, + float timeofday, float totaltime, bool use_weather) +{ //variant 1: full random //f32 heat = NoisePerlin3D(np_heat, p.X, env->getGameTime()/100, p.Z, seed); //variant 2: season change based on default heat map - auto heat = NoiseFractal2D(&(mapgen_params->bparams->np_heat), p.X, p.Z, seed); // -30..20..70 + auto heat = NoiseFractal2D( + &(mapgen_params->bparams->np_heat), p.X, p.Z, seed); // -30..20..70 // auto heat =calcHeatAtPoint(p); if (use_weather) { f32 seasonv = totaltime; seasonv /= 86400 * year_days; // season change speed - seasonv += (f32)p.X / weather_heat_width; // you can walk to area with other season + seasonv += + (f32)p.X / weather_heat_width; // you can walk to area with other season seasonv = sin(seasonv * M_PI); //heat += (weather_heat_season * (heat < offset ? 2 : 0.5)) * seasonv; // -60..0..30 - heat += (weather_heat_season) * seasonv; // -60..0..30 + heat += (weather_heat_season)*seasonv; // -60..0..30 // daily change, hotter at sun +4, colder at night -4 - heat += weather_heat_daily * (sin(cycle_shift(timeofday, -0.25) * M_PI) - 0.5); //-64..0..34 + heat += weather_heat_daily * + (sin(cycle_shift(timeofday, -0.25) * M_PI) - 0.5); //-64..0..34 } heat += p.Y / weather_heat_height; // upper=colder, lower=hotter, 3c per 1000 - if (weather_hot_core && p.Y < -(WEATHER_LIMIT-weather_hot_core)) - heat += 6000 * (1.0-((float)(p.Y - -WEATHER_LIMIT)/weather_hot_core)); //hot core, later via realms + if (weather_hot_core && p.Y < -(WEATHER_LIMIT - weather_hot_core)) + heat += 6000 * (1.0 - ((float)(p.Y - -WEATHER_LIMIT) / + weather_hot_core)); //hot core, later via realms return heat; } -weather::humidity_t BiomeManager::calcBlockHumidity(const v3pos_t &p, uint64_t seed, float timeofday, float totaltime, bool use_weather) { +weather::humidity_t BiomeManager::calcBlockHumidity(const v3pos_t &p, uint64_t seed, + float timeofday, float totaltime, bool use_weather) +{ - auto humidity = NoiseFractal2D(&(mapgen_params->bparams->np_humidity), p.X, p.Z, seed); + auto humidity = + NoiseFractal2D(&(mapgen_params->bparams->np_humidity), p.X, p.Z, seed); // auto humidity = calcHumidityAtPoint(p); if (use_weather) { @@ -344,7 +353,8 @@ weather::humidity_t BiomeManager::calcBlockHumidity(const v3pos_t &p, uint64_t s seasonv /= 86400 * weather_humidity_days; // bad weather change speed (2 days) seasonv += (f32)p.Z / weather_humidity_width; humidity += weather_humidity_season * sin(seasonv * M_PI); - humidity += weather_humidity_daily * (sin(cycle_shift(timeofday, -0.1) * M_PI) - 0.5); + humidity += + weather_humidity_daily * (sin(cycle_shift(timeofday, -0.1) * M_PI) - 0.5); } humidity += p.Y / weather_humidity_height; // upper=dry, lower=wet, 3c per 1000 From ba12216d60e51c6d22c4b9122ebc7e80e9f15d31 Mon Sep 17 00:00:00 2001 From: proller Date: Mon, 20 Oct 2025 05:14:44 +0200 Subject: [PATCH 25/36] fix --- cmake/Modules/freeminer_src.cmake | 22 ++++++++++++++++++++++ src/CMakeLists.txt | 14 ++------------ 2 files changed, 24 insertions(+), 12 deletions(-) diff --git a/cmake/Modules/freeminer_src.cmake b/cmake/Modules/freeminer_src.cmake index 022ad3a6d..d30618998 100644 --- a/cmake/Modules/freeminer_src.cmake +++ b/cmake/Modules/freeminer_src.cmake @@ -199,4 +199,26 @@ set(FMcommon_SRCS ${FMcommon_SRCS} fm_clientiface.cpp fm_serverenvironment.cpp ) + +set(FREEMINER_CLIENT_LIBRARIES + ${MSGPACK_LIBRARY} + ${ENET_LIBRARY} + ${SCTP_LIBRARY} + ${WEBSOCKETPP_LIBRARY} + ${TIFF_LIRARY} + ${OSMIUM_LIRARY} +) + +find_package(PNG REQUIRED) + +set(FREEMINER_SERVER_LIBRARIES + ${MSGPACK_LIBRARY} + ${ENET_LIBRARY} + ${SCTP_LIBRARY} + ${WEBSOCKETPP_LIBRARY} + ${TIFF_LIRARY} + ${OSMIUM_LIRARY} + ${PNG_LIBRARY} +) + # == end freeminer: diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 521d0353f..aa757e663 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -732,12 +732,7 @@ if(BUILD_CLIENT) ${GMP_LIBRARY} ${JSON_LIBRARY} - ${MSGPACK_LIBRARY} - ${ENET_LIBRARY} - ${SCTP_LIBRARY} - ${WEBSOCKETPP_LIBRARY} - ${TIFF_LIRARY} - ${OSMIUM_LIRARY} + ${FREEMINER_CLIENT_LIBRARIES} ${LUA_BIT_LIBRARY} sha256 @@ -835,12 +830,7 @@ if(BUILD_SERVER) ${ZSTD_LIBRARY} ${JSON_LIBRARY} - ${MSGPACK_LIBRARY} - ${ENET_LIBRARY} - ${SCTP_LIBRARY} - ${WEBSOCKETPP_LIBRARY} - ${TIFF_LIRARY} - ${OSMIUM_LIRARY} + ${FREEMINER_SERVER_LIBRARIES} ${LUA_LIBRARY} ${LUA_BIT_LIBRARY} From a0aa0b2e98355e1bbd99d685401cf7632a34047b Mon Sep 17 00:00:00 2001 From: proller Date: Mon, 20 Oct 2025 18:36:56 +0200 Subject: [PATCH 26/36] earth fix --- src/client/fm_client.cpp | 6 ++++++ src/fm_map.cpp | 2 +- src/mapgen/earth/http.cpp | 26 ++++++++++++++++++++++--- src/mapgen/earth/http.h | 4 +++- src/mapgen/mapgen_earth.cpp | 38 ++++++++++++++++++++++++------------- src/mapgen/mapgen_earth.h | 6 ++++-- 6 files changed, 62 insertions(+), 20 deletions(-) diff --git a/src/client/fm_client.cpp b/src/client/fm_client.cpp index 504b65add..4d1e5aad0 100644 --- a/src/client/fm_client.cpp +++ b/src/client/fm_client.cpp @@ -139,6 +139,11 @@ void Client::MakeEmerge(const Settings &settings, const MapgenType &mgtype) try { m_localserver = std::make_unique( "farmesh", findSubgame(game), false, Address{}, true); + // auto m_env = new ServerEnvironment({}, //std::move(startup_server_map), + // m_localserver.get(), &m_metrics_backend // m_metrics_backend.get() + // ); + // m_localserver->m_env = m_env; + break; } catch (const std::exception &ex) { errorstream << "Failed to make local mapgen server with game " << game @@ -155,6 +160,7 @@ void Client::MakeEmerge(const Settings &settings, const MapgenType &mgtype) g_settings->set("num_emerge_threads", "1"); m_emerge = std::make_unique( m_localserver.get(), m_localserver->m_metrics_backend.get()); + // m_emerge->env = &m_localserver->getEnv(); m_emerge->initMapgens(m_mapgen_params.get()); g_settings->set("num_emerge_threads", num_emerge_threads); } diff --git a/src/fm_map.cpp b/src/fm_map.cpp index 5db430c92..938f27e0d 100644 --- a/src/fm_map.cpp +++ b/src/fm_map.cpp @@ -333,7 +333,7 @@ weather::humidity_t ServerMap::updateBlockHumidity(ServerEnvironment *env, } auto value = - m_emerge->getFirstMapgen()->calcBlockHeat(p, getSeed(), env->getTimeOfDayF(), + m_emerge->getFirstMapgen()->calcBlockHumidity(p, getSeed(), env->getTimeOfDayF(), gametime * env->m_time_of_day_speed, env->m_use_weather); //auto value = m_emerge->biomemgr->calcBlockHumidity(p, getSeed(), env->getTimeOfDayF(),gametime * env->m_time_of_day_speed, env->m_use_weather); diff --git a/src/mapgen/earth/http.cpp b/src/mapgen/earth/http.cpp index cae01271a..be1393c64 100644 --- a/src/mapgen/earth/http.cpp +++ b/src/mapgen/earth/http.cpp @@ -4,6 +4,7 @@ #include #include #include "debug/dump.h" +#include "filesys.h" #include "httpfetch.h" #include "log.h" #include "settings.h" @@ -50,12 +51,16 @@ size_t http_to_file(const std::string &url, const std::string &path) return std::filesystem::file_size(path); }; -size_t multi_http_to_file(const std::string &name, const std::vector &links, - const std::string &path) +size_t multi_http_to_file( + const std::string &name, const std::vector &links, std::string path) { + if (path.empty()) { + path = porting::path_cache + DIR_DELIM + "earth" + "/" + name; + } + static concurrent_set http_failed; if (http_failed.contains(name)) { - return std::filesystem::file_size(path); + return std::filesystem::exists(path) ? std::filesystem::file_size(path) : 0; } if (std::filesystem::exists(path)) { @@ -83,6 +88,20 @@ size_t multi_http_to_file(const std::string &name, const std::vector links, const std::string &path) +{ + links.insert(links.begin(), +#if defined(__EMSCRIPTEN__) + "/" +#else + "http://cdn.freeminer.org/" +#endif + "earth/" + + name); + return multi_http_to_file(name, links, path); +} + size_t multi_http_to_file(const std::vector &links, const std::string &path) { static concurrent_set http_failed; @@ -115,6 +134,7 @@ size_t multi_http_to_file(const std::vector &links, const std::stri return std::filesystem::file_size(path); }; + std::string exec_to_string(const std::string &cmd) { std::unique_ptr pipe(popen(cmd.c_str(), "r"), pclose); diff --git a/src/mapgen/earth/http.h b/src/mapgen/earth/http.h index 1f780cb8c..b28fa029f 100644 --- a/src/mapgen/earth/http.h +++ b/src/mapgen/earth/http.h @@ -5,8 +5,10 @@ size_t http_to_file(const std::string &url, const std::string &zipfull); size_t multi_http_to_file(const std::string &zipfile, - const std::vector &links, const std::string &zipfull); + const std::vector &links, std::string zipfull = {}); size_t multi_http_to_file( const std::vector &links, const std::string &zipfull); +size_t multi_http_to_file_cdn(const std::string &name, std::vector links, + const std::string &path = {}); std::string exec_to_string(const std::string &cmd); diff --git a/src/mapgen/mapgen_earth.cpp b/src/mapgen/mapgen_earth.cpp index c4f85ab0f..00cfb3302 100644 --- a/src/mapgen/mapgen_earth.cpp +++ b/src/mapgen/mapgen_earth.cpp @@ -209,17 +209,26 @@ MapgenEarth::MapgenEarth(MapgenEarthParams *params_, EmergeParams *emerge) : hgt_reader.debug = 0; */ - { - const auto heat_img = m_emerge->env->m_server->getGameSpec()->path + "/" + - "mods/earth/data/earth_heat.png"; - if (std::filesystem::exists(heat_img)) { - heat_image = std::make_unique(heat_img); - } - } - if (!maps_holder) { maps_holder = std::make_unique(); } + + { + const auto heat_img = maps_holder->data_root + "/earth_heat.png"; + if (!std::filesystem::exists(heat_img)) { + const auto lock = std::lock_guard(maps_holder->download_lock); + if (!std::filesystem::exists(heat_img)) { + multi_http_to_file_cdn("earth_heat.png", {}); + } + } + + if (std::filesystem::exists(heat_img)) { + const auto lock = std::lock_guard(maps_holder->download_lock); + if (!maps_holder->heat_image) { + maps_holder->heat_image = std::make_unique(heat_img); + } + } + } } MapgenEarth::~MapgenEarth() @@ -398,7 +407,7 @@ void MapgenEarth::generateBuildings() //#include "earth/osmium-inl.h" const auto tc = pos_to_ll(node_min.X, node_min.Z); const auto tc_max = pos_to_ll(node_max.X, node_max.Z); - static const auto folder = porting::path_cache + DIR_DELIM + "earth"; + static const auto folder = maps_holder->data_root; const auto lat_dec = lat_start(tc.lat); const auto lon_dec = lon_start(tc.lon); @@ -533,10 +542,13 @@ weather::heat_t MapgenEarth::calcBlockHeat(const v3pos_t &p, uint64_t seed, { #if USE_OSMIUM const auto ll = pos_to_ll(p); - if (heat_image) { - const auto x = heat_image->width() * ((ll.lon + 180) / 360); - const auto y = (std::min( heat_image->height(), heat_image->width()/1.6 )) * ((ll.lat + 90) / 180); - const auto pixel = heat_image->get_pixel(x, y); + if (maps_holder->heat_image) { + const auto x = maps_holder->heat_image->width() * + ((int(45 + ll.lon + 180) % 360) / 360.0); + const auto y = (std::min(maps_holder->heat_image->height(), + maps_holder->heat_image->width() / 1.6)) * + ((90 - ll.lat) / 180); + const auto pixel = maps_holder->heat_image->get_pixel(x, y); auto heat = rgbToCelsiusJet(pixel->getRed(), pixel->getGreen(), pixel->getBlue()); heat += m_emerge->biomemgr->weather_heat_daily * (sin(cycle_shift(timeofday, -0.25) * M_PI) - 0.5); //-64..0..34 diff --git a/src/mapgen/mapgen_earth.h b/src/mapgen/mapgen_earth.h index e740fed40..4ae5fbbab 100644 --- a/src/mapgen/mapgen_earth.h +++ b/src/mapgen/mapgen_earth.h @@ -74,12 +74,15 @@ public: struct maps_holder_t { - hgts hgt_reader{porting::path_cache + DIR_DELIM + "earth"}; + const std::string data_root {porting::path_cache + DIR_DELIM + "earth"}; + hgts hgt_reader{ data_root }; using osm_ptr = std::shared_ptr; lru_cache osm_bbox; + std::mutex download_lock; std::mutex osm_bbox_lock; std::mutex osm_http_lock; std::mutex osm_extract_lock; + std::unique_ptr heat_image; concurrent_shared_vector files_to_delete; ~maps_holder_t(); }; @@ -119,7 +122,6 @@ public: float totaltime, bool use_weather) override; weather::humidity_t calcBlockHumidity(const v3pos_t &p, uint64_t seed, float timeofday, float totaltime, bool use_weather) override; - std::unique_ptr heat_image; struct Stat { From d723ea7143cc6688f54e6f95d8dbc822d46120c9 Mon Sep 17 00:00:00 2001 From: proller Date: Tue, 21 Oct 2025 02:11:06 +0200 Subject: [PATCH 27/36] Try use smaller network packet on windows --- src/network/connection.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/network/connection.cpp b/src/network/connection.cpp index 8575ea05b..e6cf68ac2 100644 --- a/src/network/connection.cpp +++ b/src/network/connection.cpp @@ -21,7 +21,13 @@ namespace con IConnection *createMTP(float timeout, bool ipv6, PeerHandler *handler) { // safe minimum across internet networks for ipv4 and ipv6 - constexpr u32 MAX_PACKET_SIZE = 1400; // 512; + constexpr u32 MAX_PACKET_SIZE = +#ifdef _WIN32 + 512; // TODO: find working maximum? +#else + 1350; +#endif + #if USE_MULTI return new con::ConnectionMulti(MAX_PACKET_SIZE, timeout, ipv6, handler); #elif USE_ENET From 00fcc7eb9fcca8530e068eb83c282e07943e223c Mon Sep 17 00:00:00 2001 From: proller Date: Tue, 21 Oct 2025 02:23:17 +0200 Subject: [PATCH 28/36] Fix includes --- src/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index aa757e663..14d341bd9 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -607,6 +607,7 @@ include_directories(SYSTEM #freeminer includes: include_directories( ${MSGPACK_INCLUDE_DIR} + ${PNG_INCLUDE_DIR} ) if(USE_GETTEXT) From 8e297ab31d357136ef1474ea082b4aefedbaf28d Mon Sep 17 00:00:00 2001 From: proller Date: Sun, 26 Oct 2025 06:58:48 +0100 Subject: [PATCH 29/36] Fix websocket build --- .gitmodules | 2 +- src/external/websocketpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.gitmodules b/.gitmodules index 658e0148a..54c92ef34 100644 --- a/.gitmodules +++ b/.gitmodules @@ -15,7 +15,7 @@ url = https://github.com/msgpack/msgpack-c.git [submodule "src/external/websocketpp"] path = src/external/websocketpp - url = https://github.com/zaphoyd/websocketpp.git + url = https://github.com/hanyeol/websocketpp.git [submodule "src/external/leveldb"] path = src/external/leveldb url = https://github.com/google/leveldb diff --git a/src/external/websocketpp b/src/external/websocketpp index 4dfe1be74..d116480cb 160000 --- a/src/external/websocketpp +++ b/src/external/websocketpp @@ -1 +1 @@ -Subproject commit 4dfe1be74e684acca19ac1cf96cce0df9eac2a2d +Subproject commit d116480cbdb9ecbfd66c9eb0d3591b52d532a52e From ca3af6ba3de69309c20fdae63c4b1c079661a4a0 Mon Sep 17 00:00:00 2001 From: proller Date: Sat, 15 Nov 2025 21:24:10 +0100 Subject: [PATCH 30/36] wip --- src/fm_far_calc.cpp | 11 +++++++---- src/fm_far_calc.h | 9 +++++---- src/fm_world_merge.cpp | 12 ++++++++---- src/porting.cpp | 2 ++ 4 files changed, 22 insertions(+), 12 deletions(-) diff --git a/src/fm_far_calc.cpp b/src/fm_far_calc.cpp index f7a10c35f..92f7d51ae 100644 --- a/src/fm_far_calc.cpp +++ b/src/fm_far_calc.cpp @@ -21,6 +21,7 @@ along with Freeminer. If not, see . #include "fm_far_calc.h" #include +#include #include "client/clientmap.h" #include "irr_v3d.h" @@ -45,7 +46,7 @@ block_step_t getLodStep(const MapDrawControl &draw_control, // return i; // } -/* + /* if (range >= cells + draw_control.lodmesh * 64) // cell_size = 4 return 8; if (range >= cells + draw_control.lodmesh * 32) @@ -255,9 +256,10 @@ block_step_t getFarStep(const MapDrawControl &draw_control, const v3bpos_t &ppos } v3bpos_t getFarActual(const v3bpos_t &blockpos, const v3bpos_t &ppos, block_step_t step, - const MapDrawControl &draw_control) + const MapDrawControl &draw_control, const std::optional &cell_size_pow) { - const auto blockpos_aligned_cell = align_shift(blockpos, draw_control.cell_size_pow); + const auto blockpos_aligned_cell = + align_shift(blockpos, cell_size_pow.value_or(draw_control.cell_size_pow)); const auto start = child_t{.pos = v3tpos_t((((tpos_t)ppos.X >> tree_align) << tree_align) - (tree_align_size >> 1), @@ -268,7 +270,8 @@ v3bpos_t getFarActual(const v3bpos_t &blockpos, const v3bpos_t &ppos, block_step .size = tree_size}; const auto res = find( {blockpos_aligned_cell.X, blockpos_aligned_cell.Y, blockpos_aligned_cell.Z}, - {ppos.X, ppos.Y, ppos.Z}, start, draw_control.cell_size_pow, + {ppos.X, ppos.Y, ppos.Z}, start, + cell_size_pow.value_or(draw_control.cell_size_pow), draw_control.farmesh_quality); if (res) { diff --git a/src/fm_far_calc.h b/src/fm_far_calc.h index 51add1a62..0fcd7e9c9 100644 --- a/src/fm_far_calc.h +++ b/src/fm_far_calc.h @@ -21,6 +21,7 @@ along with Freeminer. If not, see . #pragma once +#include #include "irr_v3d.h" #include "irrlichttypes.h" @@ -52,9 +53,9 @@ block_step_t getFarStepBad(const MapDrawControl &draw_control, bool inFarGrid(const v3bpos_t &blockpos, const v3bpos_t &playerblockpos, block_step_t step, const MapDrawControl &draw_control); v3bpos_t getFarActual(const v3bpos_t &blockpos, const v3bpos_t &playerblockpos, - block_step_t step, const MapDrawControl &draw_control); + block_step_t step, const MapDrawControl &draw_control, + const std::optional &cell_size_pow = {}); v3bpos_t playerBlockAlign( const MapDrawControl &draw_control, const v3bpos_t &playerblockpos); -void runFarAll(const v3bpos_t &ppos, - uint8_t cell_size_pow, uint8_t farmesh_quality, pos_t two_d, - const std::function &func); +void runFarAll(const v3bpos_t &ppos, uint8_t cell_size_pow, uint8_t farmesh_quality, + pos_t two_d, const std::function &func); diff --git a/src/fm_world_merge.cpp b/src/fm_world_merge.cpp index ff6123a80..dee3dd986 100644 --- a/src/fm_world_merge.cpp +++ b/src/fm_world_merge.cpp @@ -231,7 +231,7 @@ WorldMerger::one_block_stat_t WorldMerger::merge_one_block(MapDatabase *dbase, // TODO: skip full air; one_block_stat_t one_step_stat; if (farlights) { - constexpr auto some_magick_thinner_const = 2; // more -> less far ligts + constexpr auto some_magick_thinner_const = 1; // more -> less far ligts constexpr auto min_no_skip_ligts = 2; // do not skip this amount lights on block << farstep for (const auto &[bpos, block] : blocks) { @@ -241,12 +241,16 @@ WorldMerger::one_block_stat_t WorldMerger::merge_one_block(MapDatabase *dbase, size_t lights_in_block = 0; // TODO: apply some smart? filtering here // block_up->m_light_points.insert(block->m_light_points.begin(), block->m_light_points.end()); + const auto size = block->m_light_points.size(); + if (!size) + continue; + const auto coef = 16.0 / size; for (const auto &lp : block->m_light_points) { ++one_step_stat.lights_count; ++lights_in_block; - if ((step > 3 || lights_in_block > (min_no_skip_ligts << step)) && - (one_step_stat.lights_count % - (some_magick_thinner_const * (16 - lp.second)))) { + const auto mod = int(coef * some_magick_thinner_const * (16 - lp.second)); + if (mod && (step > 1 || lights_in_block > (min_no_skip_ligts << step)) && + (one_step_stat.lights_count % mod)) { continue; } ++one_step_stat.lights_used; diff --git a/src/porting.cpp b/src/porting.cpp index 496f5161f..7228902d6 100644 --- a/src/porting.cpp +++ b/src/porting.cpp @@ -223,7 +223,9 @@ bool detectVSCodeBuildDir(const std::string &path) "out/build/Debug", "out/build/Build", "out/build/asan", + "out/build/asan_debug", "out/build/tsan", + "out/build/tsan_debug", "out/build/msan", "out/build/ubsan", "out/build/gperf", From 1e665e6b9700b2446d0e134af633b5a66c41bcc8 Mon Sep 17 00:00:00 2001 From: proller Date: Sun, 16 Nov 2025 05:19:00 +0000 Subject: [PATCH 31/36] earth fix --- src/mapgen/mapgen_earth.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/mapgen/mapgen_earth.cpp b/src/mapgen/mapgen_earth.cpp index 00cfb3302..f68dacaa2 100644 --- a/src/mapgen/mapgen_earth.cpp +++ b/src/mapgen/mapgen_earth.cpp @@ -509,8 +509,10 @@ void MapgenEarth::generateBuildings() } { - const auto lock = std::lock_guard{maps_holder->osm_bbox_lock}; + auto lock = std::unique_lock{maps_holder->osm_bbox_lock}; + if (const auto &hdlr = maps_holder->osm_bbox.get(bbox)) { + lock.unlock(); hdlr.value()->apply(this); } } From 053542fd71d0ad5bb54e85ff1bef8dc83603e03a Mon Sep 17 00:00:00 2001 From: proller Date: Mon, 17 Nov 2025 01:06:25 +0100 Subject: [PATCH 32/36] net wip --- src/client/clientlauncher.cpp | 17 +++++++---------- src/network/enet/connection.cpp | 9 ++++----- src/network/enet/connection.h | 2 -- src/network/multi/connection.cpp | 2 +- src/network/multi/connection.h | 2 +- src/server/player_sao.cpp | 7 ------- src/server/player_sao.h | 1 - 7 files changed, 13 insertions(+), 27 deletions(-) diff --git a/src/client/clientlauncher.cpp b/src/client/clientlauncher.cpp index 3951c2ea5..3ef40d0e7 100644 --- a/src/client/clientlauncher.cpp +++ b/src/client/clientlauncher.cpp @@ -498,10 +498,6 @@ bool ClientLauncher::launch_game(std::string &error_message, start_data.world_spec = worldspecs[world_index]; } - //fm: - if (menudata.name.empty()) { - menudata.name = std::string("Guest") + itos(myrand_range(100000, 999999)); - } start_data.name = menudata.name; start_data.password = menudata.password; @@ -523,14 +519,15 @@ bool ClientLauncher::launch_game(std::string &error_message, if (!start_data.isSinglePlayer() && start_data.name.empty()) { error_message = gettext("Please choose a name!"); errorstream << error_message << std::endl; + error_message.clear(); -#ifdef __EMSCRIPTEN__ - start_data.name = std::string("Guest") + itos(myrand_range(100000, 999999)); - //resolve(false); - //return; -#else - return false; + // fm: + auto num_add = 0; +#if __EMSCRIPTEN__ + num_add = 1000000; #endif + start_data.name = std::string("Guest") + itos(myrand_range(num_add + 100000, num_add + 999999)); + // === } // If using simple singleplayer mode, override diff --git a/src/network/enet/connection.cpp b/src/network/enet/connection.cpp index 16c34da39..00805ccc6 100644 --- a/src/network/enet/connection.cpp +++ b/src/network/enet/connection.cpp @@ -92,10 +92,9 @@ const char *inet_ntop(int af, const void *src, char *dst, socklen_t size) ConnectionEnet::ConnectionEnet( u32 max_packet_size, float timeout, bool ipv6, con::PeerHandler *peerhandler) : - thread_vector("Connection", 90), m_max_packet_size(max_packet_size), - m_timeout(timeout), m_enet_host(nullptr), m_peer_id(0), - m_bc_peerhandler(peerhandler), m_last_recieved(0), m_last_recieved_warn(0), - timeout_mul(0) + thread_vector("Connection", 90), m_timeout(timeout), m_enet_host(nullptr), + m_peer_id(0), m_bc_peerhandler(peerhandler), m_last_recieved(0), + m_last_recieved_warn(0), timeout_mul(0) { timeout_mul = g_settings->getU16("timeout_mul"); if (!timeout_mul) @@ -461,7 +460,7 @@ ConnectionEventPtr ConnectionEnet::waitEvent(u32 timeout_ms) if (!timeout_ms && m_event_queue.empty()) { return ConnectionEvent::create(CONNEVENT_NONE); } - + try { return m_event_queue.pop_front(timeout_ms); } catch (const ItemNotFoundException &ex) { diff --git a/src/network/enet/connection.h b/src/network/enet/connection.h index 8d8eb3a27..e6beafb7f 100644 --- a/src/network/enet/connection.h +++ b/src/network/enet/connection.h @@ -95,8 +95,6 @@ private: MutexedQueue m_event_queue; MutexedQueue m_command_queue; - //u32 m_protocol_id {PROTOCOL_ID}; - u32 m_max_packet_size; float m_timeout; ENetHost *m_enet_host; // ENetPeer *m_peer; diff --git a/src/network/multi/connection.cpp b/src/network/multi/connection.cpp index da8231d97..c59298635 100644 --- a/src/network/multi/connection.cpp +++ b/src/network/multi/connection.cpp @@ -52,7 +52,7 @@ ConnectionMulti::ConnectionMulti( #endif #if USE_WEBSOCKET m_con_ws(std::make_shared( - max_packet_size, timeout, ipv6, peerhandler)), + 1000000, timeout, ipv6, peerhandler)), #endif #if USE_WEBSOCKET_SCTP m_con_ws_sctp(std::make_shared( diff --git a/src/network/multi/connection.h b/src/network/multi/connection.h index 6f9a19c9a..83d6783c5 100644 --- a/src/network/multi/connection.h +++ b/src/network/multi/connection.h @@ -74,7 +74,7 @@ private: #if MINETEST_TRANSPORT std::shared_ptr m_con; #endif - bool dummy; + [[maybe_unused]] bool dummy; enum class proto_name { none = 0, diff --git a/src/server/player_sao.cpp b/src/server/player_sao.cpp index cf3210bbd..0d22f80e2 100644 --- a/src/server/player_sao.cpp +++ b/src/server/player_sao.cpp @@ -52,13 +52,6 @@ PlayerSAO::PlayerSAO(ServerEnvironment *env_, RemotePlayer *player_, session_t p m_armor_groups["immortal"] = 1; } -PlayerSAO::~PlayerSAO() -{ - /*if (!m_player) - return; - --m_player->refs;*/ -} - void PlayerSAO::finalize(RemotePlayer *player, const std::set &privs) { assert(player); diff --git a/src/server/player_sao.h b/src/server/player_sao.h index ef0a6d8ed..764a838ba 100644 --- a/src/server/player_sao.h +++ b/src/server/player_sao.h @@ -61,7 +61,6 @@ public: PlayerSAO(ServerEnvironment *env_, RemotePlayer *player_, session_t peer_id_, bool is_singleplayer); - ~PlayerSAO(); ActiveObjectType getType() const override { return ACTIVEOBJECT_TYPE_PLAYER; } ActiveObjectType getSendType() const override { return ACTIVEOBJECT_TYPE_GENERIC; } std::string getDescription() override; From e52f6d23ebf6cd81e5f1824de7d39cbb8afcde07 Mon Sep 17 00:00:00 2001 From: proller Date: Mon, 17 Nov 2025 02:16:45 +0100 Subject: [PATCH 33/36] con wip --- src/network/connection.cpp | 10 +++++++--- src/network/mtp/threads.cpp | 2 +- src/network/multi/connection.cpp | 2 +- src/network/ws/threads.cpp | 2 +- 4 files changed, 10 insertions(+), 6 deletions(-) diff --git a/src/network/connection.cpp b/src/network/connection.cpp index e6cf68ac2..3a69ee23b 100644 --- a/src/network/connection.cpp +++ b/src/network/connection.cpp @@ -20,10 +20,14 @@ namespace con IConnection *createMTP(float timeout, bool ipv6, PeerHandler *handler) { + constexpr auto MAX_PACKET_SIZE_SINGLEPLAYER = 65000; + // safe minimum across internet networks for ipv4 and ipv6 - constexpr u32 MAX_PACKET_SIZE = -#ifdef _WIN32 - 512; // TODO: find working maximum? + u32 MAX_PACKET_SIZE = // simple_singleplayer_mode ? MAX_PACKET_SIZE_SINGLEPLAYER : +#if __EMSCRIPTEN__ + MAX_PACKET_SIZE_SINGLEPLAYER; +#elif defined(_WIN32) + 1350; // TODO: find working maximum? #else 1350; #endif diff --git a/src/network/mtp/threads.cpp b/src/network/mtp/threads.cpp index 83d7d73fd..6c963ddda 100644 --- a/src/network/mtp/threads.cpp +++ b/src/network/mtp/threads.cpp @@ -861,7 +861,7 @@ void *ConnectionReceiveThread::run() // use IPv6 minimum allowed MTU as receive buffer size as this is // theoretical reliable upper boundary of a udp packet for all IPv6 enabled // infrastructure - const unsigned int packet_maxsize = 1500; + const unsigned int packet_maxsize = 100050; SharedBuffer packetdata(packet_maxsize); bool packet_queued = true; diff --git a/src/network/multi/connection.cpp b/src/network/multi/connection.cpp index c59298635..bcba85aee 100644 --- a/src/network/multi/connection.cpp +++ b/src/network/multi/connection.cpp @@ -52,7 +52,7 @@ ConnectionMulti::ConnectionMulti( #endif #if USE_WEBSOCKET m_con_ws(std::make_shared( - 1000000, timeout, ipv6, peerhandler)), + 100000, timeout, ipv6, peerhandler)), #endif #if USE_WEBSOCKET_SCTP m_con_ws_sctp(std::make_shared( diff --git a/src/network/ws/threads.cpp b/src/network/ws/threads.cpp index a68e06f95..4d51ff35d 100644 --- a/src/network/ws/threads.cpp +++ b/src/network/ws/threads.cpp @@ -842,7 +842,7 @@ void *ConnectionReceiveThread::run() // use IPv6 minimum allowed MTU as receive buffer size as this is // theoretical reliable upper boundary of a udp packet for all IPv6 enabled // infrastructure - const unsigned int packet_maxsize = 1500; + const unsigned int packet_maxsize = 100050; SharedBuffer packetdata(packet_maxsize); bool packet_queued = true; From a38e8e4690376cb8a78421bf1c9e784e744ef36d Mon Sep 17 00:00:00 2001 From: proller Date: Mon, 17 Nov 2025 03:09:27 +0100 Subject: [PATCH 34/36] wip --- cmake/Modules/FindMsgPack.cmake | 2 ++ src/fm_abm.cpp | 2 +- src/fm_bitset.cpp | 24 ++++++++++++++++-------- src/fm_bitset.h | 5 +++-- src/nodedef.cpp | 2 +- 5 files changed, 23 insertions(+), 12 deletions(-) diff --git a/cmake/Modules/FindMsgPack.cmake b/cmake/Modules/FindMsgPack.cmake index 837d04349..0521b6f48 100644 --- a/cmake/Modules/FindMsgPack.cmake +++ b/cmake/Modules/FindMsgPack.cmake @@ -42,6 +42,8 @@ MARK_AS_ADVANCED(MSGPACK_INCLUDE_DIR MSGPACK_LIBRARY) include(FindPackageHandleStandardArgs) find_package_handle_standard_args(msgpack DEFAULT_MSG MSGPACK_LIBRARY MSGPACK_INCLUDE_DIR) + message(STATUS "Using system msgpack ${MSGPACK_INCLUDE_DIR} ${MSGPACK_LIBRARY}") + elseif(NOT MSGPACK_LIBRARY) set(MSGPACK_CXX14 1 CACHE INTERNAL "") set(MSGPACK_CXX17 1 CACHE INTERNAL "") diff --git a/src/fm_abm.cpp b/src/fm_abm.cpp index 130f68c27..dbea24900 100644 --- a/src/fm_abm.cpp +++ b/src/fm_abm.cpp @@ -166,7 +166,7 @@ void ABMHandler::apply(MapBlock *block, int &blocks_scanned, int &abms_run, auto &required_neighbors = activate == 1 ? ir.abmws->required_neighbors_activate : ir.abmws->required_neighbors; - if (required_neighbors.count() > 0) { + if (!required_neighbors.empty()) { v3pos_t p1; int neighbors_range = i->abmws->neighbors_range; for (p1.X = p.X - neighbors_range; p1.X <= p.X + neighbors_range; diff --git a/src/fm_bitset.cpp b/src/fm_bitset.cpp index 1a5cac2f1..1b19af957 100644 --- a/src/fm_bitset.cpp +++ b/src/fm_bitset.cpp @@ -22,26 +22,34 @@ along with Freeminer. If not, see . #include -FMBitset::FMBitset(size_t capacity): - m_bits(capacity, 0), - m_count(0) -{} +FMBitset::FMBitset(size_t capacity) : m_bits(capacity, 0), m_count(0) +{ +} -size_t FMBitset::count() { +size_t FMBitset::count() +{ return m_count; } -size_t FMBitset::size() { +size_t FMBitset::size() +{ return count(); } -void FMBitset::set(size_t index, bool value) { +void FMBitset::set(size_t index, bool value) +{ if (m_bits[index] != value) { m_bits[index] = value; m_count += value ? 1 : -1; } } -bool FMBitset::get(size_t index) { +bool FMBitset::get(size_t index) +{ return m_bits[index]; } + +bool FMBitset::empty() +{ + return !m_count; +} diff --git a/src/fm_bitset.h b/src/fm_bitset.h index fc1c0e5b4..6e1ced0c3 100644 --- a/src/fm_bitset.h +++ b/src/fm_bitset.h @@ -26,18 +26,19 @@ along with Freeminer. If not, see . #include #include -class FMBitset { +class FMBitset +{ public: FMBitset(size_t capacity); size_t count(); size_t size(); // std compat void set(size_t index, bool value); bool get(size_t index); + bool empty(); private: std::vector m_bits; size_t m_count; }; - #endif diff --git a/src/nodedef.cpp b/src/nodedef.cpp index 868dd7d3e..0cd568daa 100644 --- a/src/nodedef.cpp +++ b/src/nodedef.cpp @@ -219,7 +219,7 @@ void NodeBox::msgpack_unpack(msgpack::object o) type = (NodeBoxType)type_tmp; //if(type == NODEBOX_FIXED || type == NODEBOX_LEVELED) - if (packet.count(NODEBOX_S_FIXED)) + if (packet.contains(NODEBOX_S_FIXED)) packet[NODEBOX_S_FIXED].convert(fixed); if (type == NODEBOX_WALLMOUNTED) { From 3be0078b2a44d576c905cfa0f792a88c3a1b5609 Mon Sep 17 00:00:00 2001 From: proller Date: Tue, 18 Nov 2025 00:06:56 +0100 Subject: [PATCH 35/36] farmesh: optimize tree size --- src/client/fm_farmesh.cpp | 7 +-- src/fm_clientiface.cpp | 2 +- src/fm_far_calc.cpp | 94 ++++++++++++++++++++++++++------------- src/fm_far_calc.h | 5 ++- 4 files changed, 71 insertions(+), 37 deletions(-) diff --git a/src/client/fm_farmesh.cpp b/src/client/fm_farmesh.cpp index 7c0e31b95..2a058a376 100644 --- a/src/client/fm_farmesh.cpp +++ b/src/client/fm_farmesh.cpp @@ -277,7 +277,8 @@ int FarMesh::go_container() thread_local static const s16 farmesh_all_changed = g_settings->getU32("farmesh_all_changed"); - runFarAll(cbpos, draw_control.cell_size_pow, draw_control.farmesh_quality, 0, + runFarAll(cbpos, draw_control.cell_size_pow, draw_control.farmesh, + draw_control.farmesh_quality, 0, [this, &cbpos](const v3bpos_t &bpos, const bpos_t &size) -> bool { const block_step_t step = log(size) / log(2); @@ -320,8 +321,8 @@ int FarMesh::go_flat() // todo: maybe save blocks while cam pos not changed std::array, FARMESH_STEP_MAX> blocks; - runFarAll(cbpos, draw_control.cell_size_pow, draw_control.farmesh_quality, - cbpos.Y ?: 1, + runFarAll(cbpos, draw_control.cell_size_pow, draw_control.farmesh, + draw_control.farmesh_quality, cbpos.Y ?: 1, [this, &draw_control, &blocks]( const v3bpos_t &bpos, const bpos_t &size) -> bool { for (const auto &add : { diff --git a/src/fm_clientiface.cpp b/src/fm_clientiface.cpp index 0b182af2a..49c535f55 100644 --- a/src/fm_clientiface.cpp +++ b/src/fm_clientiface.cpp @@ -627,7 +627,7 @@ 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); - runFarAll(cbpos, cell_size_pow, farmesh_quality, false, + runFarAll(cbpos, cell_size_pow, farmesh, farmesh_quality, false, [this, &ordered, &cbpos, &use_farmesh_all_changed]( const v3bpos_t &bpos, const bpos_t &size) -> bool { if (!size) { diff --git a/src/fm_far_calc.cpp b/src/fm_far_calc.cpp index 92f7d51ae..b8242217b 100644 --- a/src/fm_far_calc.cpp +++ b/src/fm_far_calc.cpp @@ -199,30 +199,53 @@ std::optional find(const v3tpos_t &block_pos, const v3tpos_t &player_po return {}; } +const auto nearest_pow2 = [](const int v) -> int8_t { + if (v == 0) + return 0; + int p = 1; + int8_t n = 0; + while (p < v) { + p <<= 1; + ++n; + } + return n; +}; + +const auto farmesh_to_tree_pow = [](const int farmesh) -> int8_t { + return nearest_pow2(farmesh) - 1; // -2 ? TODO: test and tune +}; + +struct tree_params_t +{ #if USE_POS32 -const auto tree_pow = FARMESH_STEP_MAX; + const int16_t tree_pow = FARMESH_STEP_MAX; #else -const auto tree_pow = 12; + const auto tree_pow = 12; #endif -const auto tree_size = 1 << tree_pow; -const auto tree_align = tree_pow - 1; -const auto tree_align_size = 1 << (tree_align); -const auto external_pow = tree_pow - 2; + const int tree_size = 1 << tree_pow; + const int16_t tree_align = tree_pow - 1; + const int tree_align_size = 1 << (tree_align); + const int16_t external_pow = tree_pow - 2; +}; block_step_t getFarStepCellSize(const MapDrawControl &draw_control, const v3bpos_t &ppos, const v3bpos_t &blockpos, uint8_t cell_size_pow) { const auto blockpos_aligned_cell = align_shift(blockpos, cell_size_pow); + const tree_params_t tree_params{.tree_pow{farmesh_to_tree_pow(draw_control.farmesh)}}; const auto start = child_t{.pos = v3tpos_t( // TODO: cast to type larger than pos_t_type - (((tpos_t)ppos.X >> tree_align) << tree_align) - - (tree_align_size >> 1), - (((tpos_t)ppos.Y >> tree_align) << tree_align) - - (tree_align_size >> 1), - (((tpos_t)ppos.Z >> tree_align) << tree_align) - - (tree_align_size >> 1)), - .size = tree_size}; + (((tpos_t)ppos.X >> tree_params.tree_align) + << tree_params.tree_align) - + (tree_params.tree_align_size >> 1), + (((tpos_t)ppos.Y >> tree_params.tree_align) + << tree_params.tree_align) - + (tree_params.tree_align_size >> 1), + (((tpos_t)ppos.Z >> tree_params.tree_align) + << tree_params.tree_align) - + (tree_params.tree_align_size >> 1)), + .size = tree_params.tree_size}; const auto res = find( {blockpos_aligned_cell.X, blockpos_aligned_cell.Y, blockpos_aligned_cell.Z}, {ppos.X, ppos.Y, ppos.Z}, start, cell_size_pow, draw_control.farmesh_quality); @@ -260,14 +283,18 @@ v3bpos_t getFarActual(const v3bpos_t &blockpos, const v3bpos_t &ppos, block_step { const auto blockpos_aligned_cell = align_shift(blockpos, cell_size_pow.value_or(draw_control.cell_size_pow)); - const auto start = - child_t{.pos = v3tpos_t((((tpos_t)ppos.X >> tree_align) << tree_align) - - (tree_align_size >> 1), - (((tpos_t)ppos.Y >> tree_align) << tree_align) - - (tree_align_size >> 1), - (((tpos_t)ppos.Z >> tree_align) << tree_align) - - (tree_align_size >> 1)), - .size = tree_size}; + tree_params_t tree_params{.tree_pow{farmesh_to_tree_pow(draw_control.farmesh)}}; + + const auto start = child_t{.pos = v3tpos_t((((tpos_t)ppos.X >> tree_params.tree_align) + << tree_params.tree_align) - + (tree_params.tree_align_size >> 1), + (((tpos_t)ppos.Y >> tree_params.tree_align) + << tree_params.tree_align) - + (tree_params.tree_align_size >> 1), + (((tpos_t)ppos.Z >> tree_params.tree_align) + << tree_params.tree_align) - + (tree_params.tree_align_size >> 1)), + .size = tree_params.tree_size}; const auto res = find( {blockpos_aligned_cell.X, blockpos_aligned_cell.Y, blockpos_aligned_cell.Z}, {ppos.X, ppos.Y, ppos.Z}, start, @@ -291,7 +318,7 @@ v3bpos_t getFarActual(const v3bpos_t &blockpos, const v3bpos_t &ppos, block_step return v3bpos_t(res->pos.X, res->pos.Y, res->pos.Z); #endif } - const auto ext_align = external_pow; // + cell_size_pow; + const auto ext_align = tree_params.external_pow; // + cell_size_pow; return v3bpos_t((blockpos.X >> ext_align) << ext_align, (blockpos.Y >> ext_align) << ext_align, (blockpos.Z >> ext_align) << ext_align); @@ -368,19 +395,24 @@ void each(const each_param_t ¶m, const child_t &child) } } -void runFarAll(const v3bpos_t &ppos, uint8_t cell_size_pow, uint8_t farmesh_quality, - pos_t two_d, const std::function &func) +void runFarAll(const v3bpos_t &ppos, uint8_t cell_size_pow, int farmesh, + uint8_t farmesh_quality, pos_t two_d, + const std::function &func) { + tree_params_t tree_params{.tree_pow{farmesh_to_tree_pow(farmesh)}}; const auto start = - child_t{.pos = v3tpos_t((((tpos_t)ppos.X >> tree_align) << tree_align) - - (tree_align_size >> 1), + child_t{.pos = v3tpos_t((((tpos_t)ppos.X >> tree_params.tree_align) + << tree_params.tree_align) - + (tree_params.tree_align_size >> 1), two_d - ?: (((tpos_t)(ppos.Y) >> tree_align) << tree_align) - - (tree_align_size >> 1), - (((tpos_t)(ppos.Z) >> tree_align) << tree_align) - - (tree_align_size >> 1)), - .size{tree_size}}; + ?: (((tpos_t)(ppos.Y) >> tree_params.tree_align) + << tree_params.tree_align) - + (tree_params.tree_align_size >> 1), + (((tpos_t)(ppos.Z) >> tree_params.tree_align) + << tree_params.tree_align) - + (tree_params.tree_align_size >> 1)), + .size{tree_params.tree_size}}; const auto func_convert = [&func](const child_t &child) { return func(v3bpos_t(child.pos.X, child.pos.Y, child.pos.Z), child.size); diff --git a/src/fm_far_calc.h b/src/fm_far_calc.h index 0fcd7e9c9..5f4a32a5a 100644 --- a/src/fm_far_calc.h +++ b/src/fm_far_calc.h @@ -57,5 +57,6 @@ v3bpos_t getFarActual(const v3bpos_t &blockpos, const v3bpos_t &playerblockpos, const std::optional &cell_size_pow = {}); v3bpos_t playerBlockAlign( const MapDrawControl &draw_control, const v3bpos_t &playerblockpos); -void runFarAll(const v3bpos_t &ppos, uint8_t cell_size_pow, uint8_t farmesh_quality, - pos_t two_d, const std::function &func); +void runFarAll(const v3bpos_t &ppos, uint8_t cell_size_pow, int farmesh, + uint8_t farmesh_quality, pos_t two_d, + const std::function &func); From 994e446fabc87f1bfeab4b80a5179addaf7552d6 Mon Sep 17 00:00:00 2001 From: proller Date: Tue, 18 Nov 2025 00:09:48 +0100 Subject: [PATCH 36/36] fix --- src/mapgen/mapgen_earth.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mapgen/mapgen_earth.cpp b/src/mapgen/mapgen_earth.cpp index f68dacaa2..b6a318d67 100644 --- a/src/mapgen/mapgen_earth.cpp +++ b/src/mapgen/mapgen_earth.cpp @@ -222,7 +222,7 @@ MapgenEarth::MapgenEarth(MapgenEarthParams *params_, EmergeParams *emerge) : } } - if (std::filesystem::exists(heat_img)) { + if (std::filesystem::file_size(heat_img)) { const auto lock = std::lock_guard(maps_holder->download_lock); if (!maps_holder->heat_image) { maps_holder->heat_image = std::make_unique(heat_img);