diff --git a/.clang-format b/.clang-format index 0043866a2..a881a4b2e 100644 --- a/.clang-format +++ b/.clang-format @@ -1,4 +1,5 @@ ReflowComments: false +BreakStringLiterals: false BasedOnStyle: LLVM IndentWidth: 4 diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index baf14f86b..233cb7d79 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -97,12 +97,10 @@ if(NOT MSVC) set(ENABLE_SYSTEM_JSONCPP 0) endif() - if(USE_GPERF) - set(CMAKE_POSITION_INDEPENDENT_CODE ON) + option(ENABLE_TCMALLOC "Enable tcmalloc" 1) - # find_library(TCMALLOC_LIBRARY NAMES libtcmalloc.a tcmalloc) - # find_library(PROFILER_LIBRARY NAMES libprofiler.a profiler) - # find_library(UNWIND_LIBRARY NAMES libunwind.a unwind) + if(ENABLE_GPERF OR ENABLE_TCMALLOC) + set(CMAKE_POSITION_INDEPENDENT_CODE ON) if(CMAKE_BUILD_TYPE STREQUAL "Debug") find_library(TCMALLOC_LIBRARY NAMES tcmalloc_debug tcmalloc) @@ -110,17 +108,21 @@ if(NOT MSVC) find_library(TCMALLOC_LIBRARY NAMES tcmalloc tcmalloc_and_profiler) endif() - find_library(PROFILER_LIBRARY NAMES profiler tcmalloc_and_profiler) + if(ENABLE_GPERF) + find_library(PROFILER_LIBRARY NAMES profiler tcmalloc_and_profiler) + endif() - SET(PLATFORM_LIBS ${PLATFORM_LIBS} ${PROFILER_LIBRARY} ${TCMALLOC_LIBRARY}) - SET(OTHER_FLAGS "${OTHER_FLAGS} -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-free") - message(STATUS "Build with gperf ${PROFILER_LIBRARY} ${TCMALLOC_LIBRARY}") + set(PLATFORM_LIBS ${PLATFORM_LIBS} ${PROFILER_LIBRARY} ${TCMALLOC_LIBRARY}) + if (TCMALLOC_LIBRARY) + set(OTHER_FLAGS "${OTHER_FLAGS} -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-free") + endif() + + message(STATUS "Build with tcmalloc ${TCMALLOC_LIBRARY} ${PROFILER_LIBRARY}") endif() find_library(UNWIND_LIBRARY NAMES unwind) if(UNWIND_LIBRARY) - CHECK_CXX_SOURCE_RUNS(" #include // for backtrace int main(int argc, char *argv[]) { diff --git a/src/client/fm_farmesh.cpp b/src/client/fm_farmesh.cpp index 73acb14a4..58e12a826 100644 --- a/src/client/fm_farmesh.cpp +++ b/src/client/fm_farmesh.cpp @@ -330,7 +330,7 @@ void FarMesh::update(v3opos_t camera_pos, !m_control->farmesh_stable && ( //m_client->getEnv().getClientMap().m_far_fast && - m_speed > 200 * BS || + m_speed > 200 * BS || m_camera_pos_aligned.getDistanceFrom(camera_pos_aligned_int) > 1000); if (!timestamp_complete) { @@ -396,7 +396,7 @@ void FarMesh::update(v3opos_t camera_pos, m_client->getEnv().getClientMap().m_far_blocks_last_cam_pos = far_fast ? camera_pos_aligned_int : m_camera_pos_aligned; if (far_fast) - m_camera_pos_aligned = camera_pos_aligned_int; + m_camera_pos_aligned = camera_pos_aligned_int; } if (!planes_processed && !complete_set) { auto &clientMap = m_client->getEnv().getClientMap(); diff --git a/src/client/game.cpp b/src/client/game.cpp index 3cb9e6502..76799684a 100644 --- a/src/client/game.cpp +++ b/src/client/game.cpp @@ -4515,7 +4515,7 @@ void Game::updateFrame(ProfilerGraph *graph, RunStats *stats, f32 dtime, if (farmesh) { thread_local static const auto farmesh_range = g_settings->getS32("farmesh"); - farmesh_async.step([&, farmesh_range = farmesh_range, + farmesh_async.step([&, farmesh_range = farmesh_range, //yaw = player->getYaw(), //pitch = player->getPitch(), camera_pos = camera->getPosition(), @@ -4524,7 +4524,7 @@ void Game::updateFrame(ProfilerGraph *graph, RunStats *stats, f32 dtime, farmesh->update(camera_pos, //camera->getDirection(), camera->getFovMax(), camera->getCameraMode(), pitch, yaw, camera_offset, - //sky->getBrightness(), + //sky->getBrightness(), farmesh_range, speed); }); } diff --git a/src/mapgen/earth/hgt.cpp b/src/mapgen/earth/hgt.cpp index c9ed4cd05..1a99810d3 100644 --- a/src/mapgen/earth/hgt.cpp +++ b/src/mapgen/earth/hgt.cpp @@ -23,6 +23,7 @@ along with Freeminer. If not, see . #include "hgt.h" +#include #include #include #include @@ -36,12 +37,15 @@ along with Freeminer. If not, see . #include #include #include +#include +#include #include #include "debug/iostream_debug_helpers.h" #include "filesys.h" #include "httpfetch.h" #include "log.h" +#include "mapgen/mapgen_earth.h" #include "settings.h" #include "threading/concurrent_set.h" @@ -51,52 +55,118 @@ along with Freeminer. If not, see . #include "tiffio.h" #endif +// bad anything but works +// todo: prepare all data from all sources in one good tiled layer + hgts::hgts(const std::string &folder) : folder{folder} { fs::CreateAllDirs(folder); } -height *hgts::get(height_hgt::ll_t lat, height_hgt::ll_t lon) +height::height_t hgts::get(height_hgt::ll_t lat, height_hgt::ll_t lon) { - if (map[lat].contains(lon)) { - return map[lat][lon].get(); + + constexpr auto layers = true; + height::height_t prev_layer_height = 30000; + + const auto lat1 = height::lat_start(lat); // + 90 % 180; + const auto lon1 = height::lon_start(lon); + + if (map1[lat1].contains(lon1)) { + prev_layer_height = map1[lat1][lon1]->get(lat, lon); + + if constexpr (layers) { + if (prev_layer_height) { + return prev_layer_height; + } + } else { + return prev_layer_height; + } } + + const auto lat90 = height_gebco_tif::lat90_start(lat); // + 90 % 180; + const auto lon90 = height_gebco_tif::lon90_start(lon); + if (map90[lat90].contains(lon90)) { + const auto h = map90[lat90][lon90]->get(lat, lon); + return std::min(h, prev_layer_height); + } + + //DUMP((long)this, "notfound, will load", lat, lon, lat1, lon1, lat90, lon90, map1[lat1].contains(lon1), prev_layer_height); auto lock = std::unique_lock(mutex); - if (map[lat].contains(lon)) { - return map[lat][lon].get(); + + if (map1[lat1].contains(lon1)) { + prev_layer_height = map1[lat1][lon1]->get(lat, lon); + if constexpr (layers) { + if (prev_layer_height) { + return prev_layer_height; + } + } else { + return prev_layer_height; + } + } + if (map90[lat90].contains(lon90)) { + //DUMP("g2"); + return std::min(prev_layer_height, map90[lat90][lon90]->get(lat, lon)); } - const int lat_dec = (int)floor(lat); - const int lon_dec = (int)floor(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)) { + 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("insert", (long)this, lat, lon, folder, map.size(), map[lat].size()); - { - auto hgt = std::make_unique(folder, lat, lon); - if (hgt->load(lat_dec, lon_dec)) { - //if (hgt->ok(lat_dec, lon_dec)) - map[lat][lon] = std::move(hgt); - DUMP("hgt ok", lat, lon); - return map[lat][lon].get(); + if constexpr (layers) { + if (prev_layer_height) { + return prev_layer_height; + } + } else { + return prev_layer_height; + } + } + } + if (0) { + // WRONG, todo + //map[lat][lon]->get(lat, lon); + auto hgt = std::make_shared(folder, lat, lon); + const auto lat_dec = hgt->lat_start(lat); + const auto lon_dec = hgt->lon_start(lon); + DUMP("next tif", map1[lat_dec].contains(lon_dec)); + DUMP("load tif", lat, lon, lat_dec, lon_dec); + // TODO: actual pos check here! + if (hgt->load(lat, lon)) { + //if (hgt->ok(lat_dec, lon_dec)) + map1[lat_dec][lon_dec] = std::move(hgt); + return map1[lat_dec][lon_dec]->get(lat, lon); + } + } + if (!map90[lat90].contains(lon90)) { + // DUMP("isloaded?", map90[lat90].contains(lon90)); + auto hgt = std::make_shared(folder, lat, lon); + + //DUMP("load gebco tif", lat, lon, lat90, lon90); + + if (hgt->load(lat, lon)) { + // DUMP("loadok=", hgt->ok(lat, lon)); + map90[lat90][lon90] = std::move(hgt); + return std::min(prev_layer_height, map90[lat90][lon90]->get(lat, lon)); + } } } { - DUMP(map[lat].contains(lon)); - //map[lat][lon]->get(lat, lon); - auto hgt = std::make_unique(folder, lat, lon); - DUMP("load tif", lat, lon); - // TODO: actual pos check here! - if (hgt->load(lat_dec, lon_dec)) { - //if (hgt->ok(lat_dec, lon_dec)) - map[lat][lon] = std::move(hgt); - return map[lat][lon].get(); - } - } - { - DUMP("place dummy", lat, lon); auto hgt = std::make_unique(); - map[lat][lon] = std::move(hgt); - DUMP(lat, lon, map[lat].contains(lon)); - return map[lat][lon].get(); + const auto lat_dec = hgt->lat_start(lat); + const auto lon_dec = hgt->lon_start(lon); + // DUMP("place dummy", lat, lon, lat_dec, lon_dec, map1[lat_dec].contains(lon_dec)); + if (!map1[lat_dec].contains(lon_dec)) + map1[lat_dec][lon_dec] = std::move(hgt); + if (!map90[lat90].contains(lon90)) + map90[lat90][lon90] = std::make_unique(); + return map1[lat_dec][lon_dec]->get(lat, lon); } } @@ -104,18 +174,15 @@ std::mutex height::mutex; height_hgt::height_hgt(const std::string &folder, ll_t lat, ll_t lon) : folder{folder} { - /* - const int lat_dec = (int)floor(lat); - const int lon_dec = (int)floor(lon); - if (load(lat_dec, lon_dec)) { - static thread_local auto once = 0; - if (!once--) - DUMP("load failed", lat_dec, lon_dec); - } - */ + side_length_x_extra = 1; + tile_deg_x = 1; + tile_deg_y = 1; } height_tif::height_tif(const std::string &folder, ll_t lat, ll_t lon) : folder{folder} { + side_length_x_extra = 1; + tile_deg_x = 60; + tile_deg_y = 45; } std::string exec_to_string(const std::string &cmd) @@ -177,10 +244,10 @@ const auto multi_http_to_file = [](const auto &zipfile, const auto &zipfull) { static concurrent_set http_failed; if (http_failed.contains(zipfile)) - return; + return std::filesystem::file_size(zipfull); for (const auto &uri : links) { if (http_to_file(uri, zipfull)) - return; + return std::filesystem::file_size(zipfull); } http_failed.insert(zipfile); @@ -194,11 +261,35 @@ const auto multi_http_to_file = [](const auto &zipfile, << "\n"; std::ofstream(zipfull) << ""; // create zero file + return std::filesystem::file_size(zipfull); }; -bool height::ok(int lat_dec, int lon_dec) +bool height::ok(ll_t lat, ll_t lon) { - return lat_loaded == lat_dec && lon_loaded == lon_dec; + const auto ok = (lat_loaded == lat_start(lat) && lon_loaded == lon_start(lon)); + +#if HGT_DEBUG + if (!ok) { + static int rare = 0; + if (!(rare++ % 10000)) + DUMP("notloaded", lat, lon, + //lat_dec, lon_dec, + lat_loaded, lon_loaded, lat_start(lat), lon_start(lon), + heights.size(), file_name(lat, lon)); + } +#endif + + return ok; +} + +int height::lat_start(ll_t lat_dec) +{ + return floor(lat_dec); +} + +int height::lon_start(ll_t lon_dec) +{ + return floor(lon_dec); } const auto gen_zip_name = [](int lat_dec, int lon_dec) { @@ -213,8 +304,11 @@ const auto gen_zip_name = [](int lat_dec, int lon_dec) { return zipname; }; -bool height_hgt::load(int lat_dec, int lon_dec) +bool height_hgt::load(ll_t lat, ll_t lon) { + auto lat_dec = lat_start(lat); + auto lon_dec = lon_start(lon); + //DUMP(lat_dec, lon_dec); if (ok(lat_dec, lon_dec)) { return true; @@ -273,19 +367,20 @@ bool height_hgt::load(int lat_dec, int lon_dec) size_t filesize = 0; auto set_ratio = [&, this](const auto filesize) { - if (filesize == 2884802) { - this->seconds_per_px = 3; - } else if (filesize == 25934402) { - this->seconds_per_px = 1; - } else { - throw std::logic_error("unknown file size " + std::to_string(filesize)); - } + side_length_x = side_length_y = sqrt(filesize >> 1); - this->side_length_x = this->side_length_y = sqrt(filesize >> 1); + pixel_per_deg_x = (ll_t)side_length_x / tile_deg_x; + pixel_per_deg_y = (ll_t)side_length_y / tile_deg_y; + + seconds_per_px_x = + tile_deg_x * 3600 / (float)(side_length_x - side_length_x_extra); + seconds_per_px_y = ceil(tile_deg_y * 3600 / (float)(side_length_y)); + DUMP(tile_deg_y * 3600 / (float)(side_length_y)); + DUMP("sides", side_length_x, side_length_y, seconds_per_px_x, seconds_per_px_y); }; -// TODO: because unzip -#if 1 //!defined(_WIN32) + // TODO: because unzip + //#if 1 //!defined(_WIN32) // DUMP(filefull, zipfull); if (!std::filesystem::exists(filefull) && !std::filesystem::exists(zipfull)) { @@ -314,7 +409,7 @@ bool height_hgt::load(int lat_dec, int lon_dec) set_ratio(filesize); } } -#endif + //#endif // TODO: first try load unpached file, then unpack zip if (srtmTile.empty()) { @@ -363,7 +458,8 @@ bool height_hgt::load(int lat_dec, int lon_dec) lat_loaded = lat_dec; lon_loaded = lon_dec; DUMP("loadok", (long)this, heights.size(), lat_loaded, lon_loaded, filesize, zipname, - filename, seconds_per_px, get(lat_dec, lon_dec)); + filename, seconds_per_px_x, get(lat_dec, lon_dec), heights[0], heights[0], + heights[side_length_x]); return true; } @@ -381,21 +477,29 @@ const auto gen_zip_name_15 = [](int lat_dec, int lon_dec) { return std::string{"15-"} + c; }; -bool height_tif::load(int lat_dec, int lon_dec) +bool height_tif::load(ll_t lat, ll_t lon) { + auto lat_dec = lat_start(lat); + auto lon_dec = lon_start(lon); + #if USE_TIFF // COMPLETELY WRONG!!! //DUMP(lat_dec, lon_dec); - if (ok(lat_dec, lon_dec)) { + if (ok(lat, lon)) { return true; } auto lock = std::unique_lock(mutex); + + if (lat >= 90 || lat <= -90 || lon >= 180 || lon <= -180) + return false; + //DUMP(lat_dec, lon_dec); - if (ok(lat_dec, lon_dec)) { + if (ok(lat, lon)) { return true; } + if (lat_loading == lat_dec && lon_loading == lon_dec) { //DUMP(lat_dec, lon_dec); return false; @@ -459,7 +563,8 @@ bool height_tif::load(int lat_dec, int lon_dec) (bytes[3] * 0.144) + 0.5)) - 37; // Wrong? if (!(i % 100000)) - DUMP(i, bytes[0], bytes[2], bytes[3], bytes[4], gray); + DUMP(i, raster[i], bytes[0], bytes[2], bytes[3], bytes[4], + gray); heights[i] = gray; } @@ -477,16 +582,20 @@ bool height_tif::load(int lat_dec, int lon_dec) //DUMP(w, h, npixels); if (lat_loaded == lat_dec && lon_loaded == lon_dec) { - seconds_per_px = 15; + seconds_per_px_y = seconds_per_px_x = 15; side_length_x = w; side_length_y = h; - DUMP("tif ok", seconds_per_px, side_length_x, side_length_y); + DUMP("tif ok", seconds_per_px_x, side_length_x, side_length_y); lat_loaded = lat_dec; lon_loaded = lon_dec; + pixel_per_deg_x = (ll_t)side_length_x / tile_deg_x; + pixel_per_deg_y = (ll_t)side_length_y / tile_deg_y; + DUMP("loadok", (long)this, heights.size(), lat_loaded, lon_loaded, - zipname, tifname, seconds_per_px, get(lat_dec, lon_dec)); + zipname, tifname, seconds_per_px_x, get(lat_dec, lon_dec)); + DUMP("ppd", pixel_per_deg_x, pixel_per_deg_y); return true; } @@ -502,8 +611,313 @@ bool height_tif::load(int lat_dec, int lon_dec) return false; } +height_gebco_tif::height_gebco_tif(const std::string &folder, ll_t lat, ll_t lon) : + folder{folder} +{ + tile_deg_x = 90; + tile_deg_y = 90; +} + +bool height_gebco_tif::ok(ll_t lat, ll_t lon) +{ + + const auto ok = (lat_loaded == lat90_start(lat) && lon_loaded == lon90_start(lon)); + +#if HGT_DEBUG + if (!ok) { + static int rare = 0; + if (!(rare++ % 10000)) + DUMP("notloaded", lat, lon, + //lat_dec, lon_dec, + lat_loaded, lon_loaded, lat90_start(lat), lon90_start(lon), + heights.size(), file_name(lat, lon)); + } +#endif + + return ok; +} + +int height_gebco_tif::lat90_start(ll_t lat_dec) +{ + return floor(lat_dec / 90.0 + 1) * 90; +} +int height_gebco_tif::lon90_start(ll_t lon_dec) +{ + return floor(lon_dec / 90.0) * 90; +} + +std::string height_gebco_tif::file_name(ll_t lat, ll_t lon) +{ + + /* + 0 + 1 | 2 | 3 | 4 +0 ----|---|---|---- + 5 | 6 | 7 | 8 + +gebco_2023_sub_ice_n90.0_s0.0_w-180.0_e-90.0.tif 1 north america +gebco_2023_sub_ice_n90.0_s0.0_w-90.0_e0.0.tif 2 atlantica +gebco_2023_sub_ice_n90.0_s0.0_w0.0_e90.0.tif - 3 europe lat = 46.4085; float lon = 11.8393 +gebco_2023_sub_ice_n90.0_s0.0_w90.0_e180.0.tif 4 eurasia +gebco_2023_sub_ice_n0.0_s-90.0_w-180.0_e-90.0.tif 5 ocean +gebco_2023_sub_ice_n0.0_s-90.0_w-90.0_e0.0.tif 6 south america +gebco_2023_sub_ice_n0.0_s-90.0_w0.0_e90.0.tif 7 south africa +gebco_2023_sub_ice_n0.0_s-90.0_w90.0_e180.0.tif 8 australia +*/ + std::string name; // = "gebco_2023_sub_ice_"; + name += 'n'; + const auto h_start = abs(lat90_start(lat)); + name += std::to_string(h_start); + name += ".0_s"; + const auto h_end = h_start - 90; + name += std::to_string(h_end); + name += ".0_w"; + const auto w_start = lon90_start(lon); // (lon_dec / 90) * 90; + name += std::to_string(w_start); + name += ".0_e"; + const auto w_end = w_start + 90; + name += std::to_string(w_end); + name += ".0"; + DUMP(lat, lon, name, h_start, h_end, w_start, w_end); + return name; +} + +bool height_gebco_tif::load(ll_t lat, ll_t lon) +{ + const auto lat_dec = lat90_start(lat); + const auto lon_dec = lon90_start(lon); + +#if TEST + static int once = 0; + if (!once++) + for (const auto &t : std::vector>{ + {0, 0, "n90.0_s0.0_w0.0_e90.0"}, {1, 1, "n90.0_s0.0_w0.0_e90.0"}, + {-1, 1, "n0.0_s-90.0_w0.0_e90.0"}, {1, -1, "n90.0_s0.0_w-90.0_e0.0"}, + {-1, -1, "n0.0_s-90.0_w-90.0_e0.0"}, + {1, 100, "n90.0_s0.0_w90.0_e180.0"}, + {-1, -100, "n0.0_s-90.0_w-180.0_e-90.0"}, {-300, 0, ""}, + {0, 300, ""}}) { + const auto fn = folder + "/" + "gebco_2023_sub_ice_" + + file_name(get<0>(t), get<1>(t)) + ".tif"; + DUMP("testname", get<0>(t), get<1>(t), file_name(get<0>(t), get<1>(t)), + get<2>(t), std::filesystem::exists(fn)); + if (!get<2>(t).empty() && get<2>(t) != file_name(get<0>(t), get<1>(t))) { + DUMP("testfail"); + //exit(1); + } + } +#endif + +#if USE_TIFF + + //DUMP(lat_dec, lon_dec); + if (ok(lat, lon)) { + return true; + } + auto lock = std::unique_lock(mutex); + //DUMP(lat_dec, lon_dec); + if (ok(lat, lon)) { + return true; + } + if (lat_loading == lat_dec && lon_loading == lon_dec) { + //DUMP(lat_dec, lon_dec); + return false; + } + DUMP("loadstart", (long)this, lat_dec, lon_dec, lat_loading, lon_loading, lat_loaded, + lon_loaded); + TimeTaker timer("tiff load"); + + lat_loading = lat_dec; + lon_loading = lon_dec; + + { + const auto name = file_name(lat, lon); + auto tifname = folder + "/" + "gebco_2023_sub_ice_" + name + ".tif"; + DUMP(name, tifname); + if (0) // too big zips + { + std::string zipfile = "gebco_2023_sub_ice_topo_geotiff.zip"; + std::string zipfull = folder + "/" + zipfile; + if (!std::filesystem::exists(tifname) && !std::filesystem::exists(zipfull)) { + if (multi_http_to_file(zipfile, + {"https://www.bodc.ac.uk/data/open_download/gebco/gebco_2023_sub_ice_topo/geotiff/"}, + zipfull)) { + exec_to_string( + "unzip " + zipfull + " -d " + folder); // TODO just exec + } + } + + if (!std::filesystem::exists(tifname) && !std::filesystem::exists(zipfull)) { + zipfile = "gebco_2023_geotiff.zip"; + zipfull = folder + "/" + zipfile; + tifname = folder + "/" + "gebco_2023_" + name + ".tif"; + if (multi_http_to_file(zipfile, + {"https://www.bodc.ac.uk/data/open_download/gebco/gebco_2023_tid/geotiff/"}, + zipfull)) { + exec_to_string( + "unzip " + zipfull + " -d " + folder); // TODO just exec + } + } + } else { + std::cerr + << "Want " << tifname << " from " + << "https://www.bodc.ac.uk/data/open_download/gebco/gebco_2023_sub_ice_topo/geotiff/" + << " or " + << "https://www.bodc.ac.uk/data/open_download/gebco/gebco_2023_tid/geotiff/" + << "\n"; + } + + //DUMP(tifname, std::filesystem::exists(tifname)); + + if (!std::filesystem::exists(tifname)) { + tifname = folder + "/" + "gebco_2023_" + name + ".tif"; + } + //DUMP("loadtifname", tifname, std::filesystem::exists(tifname)); + if (std::filesystem::exists(tifname)) { + DUMP("open tif", tifname, std::filesystem::file_size(tifname)); + if (const auto tif = TIFFOpen(tifname.c_str(), "r"); tif) { + uint32_t w = 0; + uint32_t h = 0; + TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &w); + TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &h); + if (!w || !h) { + return false; + } + + const size_t npixels = (w + 1) * (h + 1); + //DUMP("tiff size", w, h, npixels); + heights.resize(npixels); + + //w = TIFFScanlineSize(tif) >> 1; + const tdata_t buf = _TIFFmalloc(TIFFScanlineSize(tif)); + for (uint32_t row = 0; row < h; ++row) { + TIFFReadScanline(tif, buf, row, 0); + +#if HGT_DEBUG + if (!(row % 10000)) + DUMP(row, TIFFNumberOfStrips(tif), TIFFStripSize(tif), + ((uint8_t *)buf)[0], ((uint8_t *)buf)[2], + ((uint8_t *)buf)[3], ((uint8_t *)buf)[4]); +#endif + + int16_t height; + for (uint32_t i = 0; i < w; ++i) { + height = (((uint8_t *)buf)[i << 1]) | + (((uint8_t *)buf)[(i << 1) + 1] << 8); + if (height == -32768 || height == 31727) { + height = 0; + } + const auto dest = i + row * (w + 1); +#if HGT_DEBUG + if (!(i % 10000) && !(row % 10000)) + DUMP("fill", i, w, h, row, dest, height, //height2, + ((uint8_t *)buf)[(i << 1)], + ((uint8_t *)buf)[(i << 1) + 1], + ((uint8_t *)buf)[(i << 1) + 2], + ((uint8_t *)buf)[(i << 1) + 3]); +#endif + + heights[dest] = height; + } + const auto dest = w + row * (w + 1); + heights[dest] = height; // hack for interpolation x+1 get + //DUMP("xhck", w, dest, height); + } + + // hack for interpolation y+1 get + for (uint32_t i = 0; i <= w; ++i) { + const auto src = i + (h - 1) * (w + 1); + const auto dest = i + h * (w + 1); + //DUMP("yhck", i, src, dest, heights[src]); + heights[dest] = heights[src]; + } + + _TIFFfree(buf); + TIFFClose(tif); + + lat_loaded = lat_dec; + lon_loaded = lon_dec; + + side_length_x = w; + side_length_y = h; + + seconds_per_px_x = + tile_deg_x * 3600 / ((float)side_length_x - side_length_x_extra); + seconds_per_px_y = tile_deg_y * 3600 / ((float)side_length_y); + + pixel_per_deg_x = (ll_t)side_length_x / tile_deg_x; + pixel_per_deg_y = (ll_t)side_length_y / tile_deg_y; + +#if HGT_DEBUG + DUMP("tif ok", seconds_per_px_x, side_length_x, side_length_y, + seconds_per_px_x, seconds_per_px_y); + DUMP("loadok", (long)this, heights.size(), lat_loaded, lon_loaded, + tifname, seconds_per_px_x, get(lat_dec, lon_dec)); + DUMP("testread", read(0, 0), read(0, side_length_x - 1), + read(side_length_y - 1, side_length_x - 1), + read(side_length_y - 1, 0)); +#endif + + return true; + } + } + } + +#endif + + DUMP("load not ok", (long)this, heights.size(), lat_loaded, lon_loaded, + seconds_per_px_x, get(lat_dec, lon_dec)); + return false; +} + +std::tuple height_gebco_tif::ll_to_xy(ll_t lat, ll_t lon) +{ + const ll_t lat_seconds = (lat_loaded - lat) * 60 * 60; + const ll_t lon_seconds = (lon - lon_loaded) * 60 * 60; + + const size_t y = ((lat_loaded - lat) * pixel_per_deg_y) - 1; + const size_t x = (lon - lon_loaded) * pixel_per_deg_x; + + return {x, y, lat_seconds, lon_seconds}; +} + +int16_t height_gebco_tif::read(uint16_t y, uint16_t x) +{ + const int pos = (((int)side_length_x - side_length_x_extra + 1) * y) + x; + +#if HGT_DEBGUG + static int rare = 0; + if (!(rare++ % 1000000)) + DUMP("read", x, y, + // row, col, + pos, side_length_x, side_length_x_extra, side_length_y, heights[pos]); +#endif + + return heights[pos]; +} + +std::tuple height_hgt::ll_to_xy(ll_t lat, ll_t lon) +{ + + const ll_t lat_seconds = (lat - (ll_t)lat_loaded) * 60 * 60; + const ll_t lon_seconds = (lon - (ll_t)lon_loaded) * 60 * 60; + const int y = lat_seconds / seconds_per_px_y; + const int x = lon_seconds / seconds_per_px_x; + return {x, y, lat_seconds, lon_seconds}; +} + +std::tuple height_tif::ll_to_xy(ll_t lat, ll_t lon) +{ + const ll_t lat_seconds = (lat - (ll_t)lat_loaded) * 60 * 60; + const ll_t lon_seconds = (lon - (ll_t)lon_loaded) * 60 * 60; + const size_t y = ((lat - lat_loaded) * pixel_per_deg_y) - 1; + const size_t x = (lon - lon_loaded) * pixel_per_deg_x; + + return {x, y, lat_seconds, lon_seconds}; +} + /** Pixel idx from left bottom corner (0-1200) */ -int16_t height::read(int16_t y, int16_t x) +int16_t height_hgt::read(uint16_t y, uint16_t x) { const int row = (side_length_x - 1) - y; const int col = x; @@ -511,33 +925,52 @@ int16_t height::read(int16_t y, int16_t x) return heights[pos]; } -float height::get(ll_t lat, ll_t lon) +height::height_t height::get(ll_t lat, ll_t lon) { - const int lat_dec = (int)floor(lat); - const int lon_dec = (int)floor(lon); - - if (!ok(lat_dec, lon_dec)) { - // DUMP("notloaded", lat, lon, lat_dec, lon_dec, lat_loaded, lon_loaded, lat_loading, lon_loading, heights.size()); + if (!ok(lat, lon)) { + /*static int rare = 0; + if (!(rare++ % 10000)) + DUMP("notloaded", lat, lon, + //lat_dec, lon_dec, + lat_loaded, lon_loaded, lat_start(lat), lon_start(lon), + heights.size(), file_name(lat, lon));*/ return {}; } - const ll_t lat_seconds = (lat - (ll_t)lat_loaded) * 60 * 60; - const ll_t lon_seconds = (lon - (ll_t)lon_loaded) * 60 * 60; - - const int y = lat_seconds / seconds_per_px; - const int x = lon_seconds / seconds_per_px; + const auto [x, y, lat_seconds, lon_seconds] = ll_to_xy(lat, lon); +#if HGT_DEBUG + const auto h = read(y, x); + { + static int rare = 0; + if (h > 9000 || h < -10000 || !(rare++ % 1000000)) + DUMP("tst", h, x, y, + //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); + } +#endif const int16_t height[] = { read(y + 1, x), read(y + 1, x + 1), read(y, x), read(y, x + 1), }; - // return height[2]; // debug not interpolated + +#if HGT_DEBUG + static int rare = 0; + if (height[2] > 9000 || height[2] < -10000 || !(rare++ % 100000)) + DUMP("tst", height[2], x, y, + //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 +#endif // ratio where X lays - const float dy = fmod(lat_seconds, seconds_per_px) / seconds_per_px; - const float dx = fmod(lon_seconds, seconds_per_px) / seconds_per_px; + const float dy = fmod(lat_seconds, seconds_per_px_x) / seconds_per_px_x; + const float dx = fmod(lon_seconds, seconds_per_px_y) / seconds_per_px_y; // Bilinear interpolation // h0------------h1 diff --git a/src/mapgen/earth/hgt.h b/src/mapgen/earth/hgt.h index 1a0c252e3..5cf935706 100644 --- a/src/mapgen/earth/hgt.h +++ b/src/mapgen/earth/hgt.h @@ -21,6 +21,7 @@ along with Freeminer. If not, see . #pragma once +#include #include #include #include @@ -30,21 +31,33 @@ along with Freeminer. If not, see . class height { +public: + using ll_t = float; + using height_t = float; + protected: - uint16_t side_length_x = 0, side_length_y = 0; // = 3601; - uint8_t seconds_per_px = 0; + uint16_t side_length_x = 0, side_length_y = 0, side_length_x_extra = 0; // = 3601; + uint8_t tile_deg_x{}, tile_deg_y{}; + uint8_t seconds_per_px_x = 0, seconds_per_px_y = 0; int lat_loaded = 200; int lon_loaded = 200; + uint16_t pixel_per_deg_x, pixel_per_deg_y; + std::vector heights; static std::mutex mutex; - int16_t read(int16_t y, int16_t x); + virtual int16_t read(uint16_t y, uint16_t x) { return -30000; }; + virtual std::string file_name(ll_t lat, ll_t lon) { return {}; }; + +protected: + virtual std::tuple ll_to_xy(ll_t lat, ll_t lon) = 0; public: - using ll_t = float; - virtual bool load(int lat_dec, int lon_dec) {}; - bool ok(int lat_dec, int lon_dec); - float get(ll_t lat, ll_t lon); + virtual bool load(ll_t lat, ll_t lon) { return true; }; + virtual bool ok(ll_t lat, ll_t lon); + height_t get(ll_t lat, ll_t lon); + static int lat_start(ll_t lat); + static int lon_start(ll_t lon); }; class height_hgt : public height { @@ -53,9 +66,13 @@ private: int lat_loading = 200; int lon_loading = 200; +protected: + std::tuple ll_to_xy(ll_t lat, ll_t lon) override; + int16_t read(uint16_t y, uint16_t x) override; + public: height_hgt(const std::string &folder, ll_t lat, ll_t lon); - bool load(int lat_dec, int lon_dec) override; + bool load(ll_t lat, ll_t lon) override; }; class height_tif : public height @@ -64,25 +81,54 @@ class height_tif : public height int lat_loading = 200; int lon_loading = 200; +protected: + std::tuple ll_to_xy(ll_t lat, ll_t lon) override; + public: height_tif(const std::string &folder, ll_t lat, ll_t lon); - bool load(int lat_dec, int lon_dec) override; + bool load(ll_t lat, ll_t lon) override; +}; + +class height_gebco_tif : public height +{ + const std::string folder; + int lat_loading = 200; + int lon_loading = 200; + std::string file_name(ll_t lat, ll_t lon) override; + +protected: + std::tuple ll_to_xy(ll_t lat, ll_t lon) override; + int16_t read(uint16_t y, uint16_t x) override; + +public: + height_gebco_tif(const std::string &folder, ll_t lat, ll_t lon); + bool load(ll_t lat, ll_t lon) override; + bool ok(ll_t lat, ll_t lon) override; + static int lat90_start(ll_t lat); + static int lon90_start(ll_t lon); }; class height_dummy : public height { +protected: + std::tuple ll_to_xy(ll_t lat, ll_t lon) override + { + return {}; + }; public: //height_dummy(ll_t lat, ll_t lon); + static int lat_start(ll_t lat) { return -300; }; + static int lon_start(ll_t lon) { return -300; }; }; class hgts { - std::map>> map; + std::map>> map1, map90; const std::string folder; std::mutex mutex; public: hgts(const std::string &folder); - height *get(height::ll_t lat, height::ll_t lon); + height::height_t get(height::ll_t lat, height::ll_t lon); }; \ No newline at end of file diff --git a/src/mapgen/mapgen_earth.cpp b/src/mapgen/mapgen_earth.cpp index 0f243530b..61c10d18d 100644 --- a/src/mapgen/mapgen_earth.cpp +++ b/src/mapgen/mapgen_earth.cpp @@ -219,19 +219,23 @@ ll MapgenEarth::pos_to_ll(const pos_t x, const pos_t z) constexpr double EQUATOR_LEN{40075696.0}; const auto lon = ((ll_t)x * scale.X) / (EQUATOR_LEN / 360) + center.X; const auto lat = ((ll_t)z * scale.Z) / (EQUATOR_LEN / 360) + center.Z; - return {(ll_t)lat, (ll_t)lon}; + if (lat < 90 && lat > -90 && lon < 180 && lon > -180) { + return {(ll_t)lat, (ll_t)lon}; + } else { + return {89.9999, 0}; + } } pos_t MapgenEarth::get_height(pos_t x, pos_t z) { const auto tc = pos_to_ll(x, z); - auto y = hgt_reader.get(tc.lat, tc.lon)->get(tc.lat, tc.lon); - return y * scale.Y - center.Y; + auto y = hgt_reader.get(tc.lat, tc.lon); + return y / scale.Y - center.Y; } int MapgenEarth::getSpawnLevelAtPoint(v2pos_t p) { - return get_height(p.X, p.Y) + 2; + return std::max(2, get_height(p.X, p.Y) + 2); } int MapgenEarth::generateTerrain() @@ -239,7 +243,6 @@ int MapgenEarth::generateTerrain() MapNode n_ice(c_ice); u32 index = 0; v3pos_t em = vm->m_area.getExtent(); - //auto zstride_1d = csize.X * (csize.Y + 1); 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++) { @@ -251,9 +254,7 @@ int MapgenEarth::generateTerrain() 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++) { - // auto [have, d] = calc_point(x,y,z); bool underground = height >= y; - if (underground) { if (!vm->m_data[i]) { vm->m_data[i] = layers_get(0, 1); diff --git a/src/network/fm_lan.cpp b/src/network/fm_lan.cpp index dd9fa612d..cdaf1bf3e 100644 --- a/src/network/fm_lan.cpp +++ b/src/network/fm_lan.cpp @@ -23,11 +23,11 @@ along with Freeminer. If not, see . #include #include "convert_json.h" #include "socket.h" -#include "../util/string.h" #include "../log_types.h" #include "../settings.h" #include "../version.h" #include "networkprotocol.h" +#include "serverlist.h" //copypaste from ../socket.cpp #ifdef _WIN32 @@ -62,13 +62,15 @@ typedef int socklen_t; typedef int socket_t; #endif - const static unsigned short int adv_port = 29998; static std::string ask_str; -lan_adv::lan_adv() : thread_vector("lan_adv") { } +lan_adv::lan_adv() : thread_vector("lan_adv") +{ +} -void lan_adv::ask() { +void lan_adv::ask() +{ reanimate(); if (ask_str.empty()) { @@ -81,7 +83,8 @@ void lan_adv::ask() { send_string(ask_str); } -void lan_adv::send_string(const std::string& str) { +void lan_adv::send_string(const std::string &str) +{ try { sockaddr_in addr = {}; addr.sin_family = AF_INET; @@ -89,9 +92,10 @@ void lan_adv::send_string(const std::string& str) { addr.sin_addr.s_addr = htonl(INADDR_BROADCAST); UDPSocket socket_send(false); int set_option_on = 1; - setsockopt(socket_send.GetHandle(), SOL_SOCKET, SO_BROADCAST, (const char*) &set_option_on, sizeof(set_option_on)); + setsockopt(socket_send.GetHandle(), SOL_SOCKET, SO_BROADCAST, + (const char *)&set_option_on, sizeof(set_option_on)); socket_send.Send(Address(addr), str.c_str(), str.size()); - } catch(const std::exception &e) { + } catch (const std::exception &e) { verbosestream << "udp broadcast send4 fail " << e.what() << "\n"; } @@ -107,7 +111,7 @@ void lan_adv::send_string(const std::string& str) { if (ifa->ifa_addr->sa_family != AF_INET6) continue; - auto sa = *((struct sockaddr_in6*)ifa->ifa_addr); + auto sa = *((struct sockaddr_in6 *)ifa->ifa_addr); if (sa.sin6_scope_id) scopes.push_back(sa.sin6_scope_id); @@ -122,7 +126,9 @@ void lan_adv::send_string(const std::string& str) { if (scopes.empty()) scopes.push_back(0); - struct addrinfo hints { }; + struct addrinfo hints + { + }; hints.ai_family = AF_INET6; hints.ai_socktype = SOCK_DGRAM; hints.ai_flags = AI_V4MAPPED | AI_ADDRCONFIG; @@ -130,21 +136,22 @@ void lan_adv::send_string(const std::string& str) { if (!getaddrinfo("ff02::1", nullptr, &hints, &result)) { for (auto info = result; info; info = info->ai_next) { try { - sockaddr_in6 addr = *((struct sockaddr_in6*)info->ai_addr); + sockaddr_in6 addr = *((struct sockaddr_in6 *)info->ai_addr); addr.sin6_port = htons(adv_port); UDPSocket socket_send(true); int set_option_on = 1; - setsockopt(socket_send.GetHandle(), SOL_SOCKET, SO_BROADCAST, (const char*) &set_option_on, sizeof(set_option_on)); + setsockopt(socket_send.GetHandle(), SOL_SOCKET, SO_BROADCAST, + (const char *)&set_option_on, sizeof(set_option_on)); auto use_scopes = scopes; if (addr.sin6_scope_id) { use_scopes.clear(); use_scopes.push_back(addr.sin6_scope_id); } - for (auto & scope : use_scopes) { + for (auto &scope : use_scopes) { addr.sin6_scope_id = scope; socket_send.Send(Address(addr), str.c_str(), str.size()); } - } catch(const std::exception &e) { + } catch (const std::exception &e) { verbosestream << "udp broadcast send6 fail " << e.what() << "\n"; } } @@ -152,12 +159,14 @@ void lan_adv::send_string(const std::string& str) { } } -void lan_adv::serve(unsigned short port) { +void lan_adv::serve(unsigned short port) +{ server_port = port; restart(); } -void * lan_adv::run() { +void *lan_adv::run() +{ EXCEPTION_HANDLER_BEGIN; @@ -165,21 +174,27 @@ void * lan_adv::run() { UDPSocket socket_recv(true); int set_option_off = 0, set_option_on = 1; - setsockopt(socket_recv.GetHandle(), SOL_SOCKET, SO_REUSEADDR, (const char*) &set_option_on, sizeof(set_option_on)); + setsockopt(socket_recv.GetHandle(), SOL_SOCKET, SO_REUSEADDR, + (const char *)&set_option_on, sizeof(set_option_on)); #ifdef SO_REUSEPORT - setsockopt(socket_recv.GetHandle(), SOL_SOCKET, SO_REUSEPORT, (const char*) &set_option_on, sizeof(set_option_on)); + setsockopt(socket_recv.GetHandle(), SOL_SOCKET, SO_REUSEPORT, + (const char *)&set_option_on, sizeof(set_option_on)); #endif - setsockopt(socket_recv.GetHandle(), SOL_SOCKET, SO_BROADCAST, (const char*) &set_option_on, sizeof(set_option_on)); - setsockopt(socket_recv.GetHandle(), IPPROTO_IPV6, IPV6_V6ONLY, (const char*) &set_option_off, sizeof(set_option_off)); + setsockopt(socket_recv.GetHandle(), SOL_SOCKET, SO_BROADCAST, + (const char *)&set_option_on, sizeof(set_option_on)); + setsockopt(socket_recv.GetHandle(), IPPROTO_IPV6, IPV6_V6ONLY, + (const char *)&set_option_off, sizeof(set_option_off)); socket_recv.setTimeoutMs(200); try { socket_recv.Bind(Address(in6addr_any, adv_port)); } catch (const std::exception &e) { - warningstream << m_name << ": cant bind ipv6 address [" << e.what() << "], trying ipv4. " << std::endl; + warningstream << m_name << ": cant bind ipv6 address [" << e.what() + << "], trying ipv4. " << std::endl; try { socket_recv.Bind(Address((u32)INADDR_ANY, adv_port)); } catch (const std::exception &e) { - warningstream << m_name << ": cant bind ipv4 too [" << e.what() << "]" << std::endl; + warningstream << m_name << ": cant bind ipv4 too [" << e.what() << "]" + << std::endl; return nullptr; } } @@ -188,76 +203,83 @@ void * lan_adv::run() { const auto proto = g_settings->get("server_proto"); const unsigned int packet_maxsize = 16384; - char buffer [packet_maxsize]; + char buffer[packet_maxsize]; Json::Reader reader; std::string answer_str; Json::Value server; if (server_port) { - server["name"] = g_settings->get("server_name"); - server["description"] = g_settings->get("server_description"); - server["version"] = g_version_string; + server["name"] = g_settings->get("server_name"); + server["description"] = g_settings->get("server_description"); + server["version"] = g_version_string; bool strict_checking = g_settings->getBool("strict_protocol_version_checking"); - server["proto_min"] = strict_checking ? LATEST_PROTOCOL_VERSION : SERVER_PROTOCOL_VERSION_MIN; - server["proto_max"] = strict_checking ? LATEST_PROTOCOL_VERSION : SERVER_PROTOCOL_VERSION_MAX; - server["url"] = g_settings->get("server_url"); - server["creative"] = g_settings->getBool("creative_mode"); - server["damage"] = g_settings->getBool("enable_damage"); - server["password"] = g_settings->getBool("disallow_empty_password"); - server["pvp"] = g_settings->getBool("enable_pvp"); - server["port"] = server_port; - server["clients"] = clients_num.load(); - server["clients_max"] = g_settings->getU16("max_users"); - server["proto"] = g_settings->get("server_proto"); + server["proto_min"] = + strict_checking ? LATEST_PROTOCOL_VERSION : SERVER_PROTOCOL_VERSION_MIN; + server["proto_max"] = + strict_checking ? LATEST_PROTOCOL_VERSION : SERVER_PROTOCOL_VERSION_MAX; + server["url"] = g_settings->get("server_url"); + server["creative"] = g_settings->getBool("creative_mode"); + server["damage"] = g_settings->getBool("enable_damage"); + server["password"] = g_settings->getBool("disallow_empty_password"); + server["pvp"] = g_settings->getBool("enable_pvp"); + server["port"] = server_port; + server["clients"] = clients_num.load(); + server["clients_max"] = g_settings->getU16("max_users"); + server["proto"] = g_settings->get("server_proto"); + + ServerList::addMultiProto(server, server_port); send_string(fastWriteJson(server)); } - while(!stopRequested()) { + while (!stopRequested()) { EXCEPTION_HANDLER_BEGIN; - Address addr; - int rlen = socket_recv.Receive(addr, buffer, packet_maxsize); - if (rlen <= 0) - continue; - Json::Value p; - if (!reader.parse(std::string(buffer, rlen), p)) { - //errorstream << "cant parse "<< s << "\n"; - continue; + Address addr; + int rlen = socket_recv.Receive(addr, buffer, packet_maxsize); + if (rlen <= 0) + continue; + Json::Value p; + if (!reader.parse(std::string(buffer, rlen), p)) { + //errorstream << "cant parse "<< s << "\n"; + continue; + } + auto addr_str = addr.serializeString(); + auto now = porting::getTimeMs(); + //errorstream << " a=" << addr.serializeString() << " : " << addr.getPort() << " l=" << rlen << " b=" << p << " ; server=" << server_port << "\n"; + if (server_port) { + if (p["cmd"] == "ask" && limiter[addr_str] < now) { + (clients_num.load() ? infostream : actionstream) + << "lan: want play " << addr_str << " " << p["proto"] + << std::endl; + + server["clients"] = clients_num.load(); + answer_str = fastWriteJson(server); + + limiter[addr_str] = now + 3000; + UDPSocket socket_send(true); + addr.setPort(adv_port); + socket_send.Send(addr, answer_str.c_str(), answer_str.size()); } - auto addr_str = addr.serializeString(); - auto now = porting::getTimeMs(); - //errorstream << " a=" << addr.serializeString() << " : " << addr.getPort() << " l=" << rlen << " b=" << p << " ; server=" << server_port << "\n"; - if (server_port) { - if (p["cmd"] == "ask" && limiter[addr_str] < now) { - (clients_num.load() ? infostream : actionstream) << "lan: want play " << addr_str << " " << p["proto"] << std::endl; - - server["clients"] = clients_num.load(); - answer_str = fastWriteJson(server); - - limiter[addr_str] = now + 3000; - UDPSocket socket_send(true); - addr.setPort(adv_port); - socket_send.Send(addr, answer_str.c_str(), answer_str.size()); - } - } else { - if (p["cmd"] == "ask") { - actionstream << "lan: want play " << addr_str << " " << p["proto"] << std::endl; - } - if (p["port"].isInt()) { - p["address"] = addr_str; - auto key = addr_str + ":" + p["port"].asString(); - if (p["cmd"].asString() == "shutdown") { - //infostream << "server shutdown " << key << "\n"; - collected.erase(key); - fresh = true; - } else if (p["proto"] == proto) { - if (!collected.count(key)) - actionstream << "lan server start " << key << "\n"; - collected.insert_or_assign(key, p); - fresh = true; - } - } - - //errorstream<<" current list: ";for (auto & i : collected) {errorstream<< i.first <<" ; ";}errorstream<. */ -#ifndef FM_LAN_HEADER -#define FM_LAN_HEADER +#pragma once +#include #include #include -#include "json/json.h" #include "../threading/thread_vector.h" #include "../threading/concurrent_map.h" - -class lan_adv : public thread_vector { +class lan_adv : public thread_vector +{ public: - void * run(); + void *run(); lan_adv(); void ask(); - void send_string(const std::string& str); + void send_string(const std::string &str); void serve(unsigned short port); @@ -44,6 +43,3 @@ public: private: unsigned short server_port = 0; }; - - -#endif \ No newline at end of file diff --git a/src/serverlist.cpp b/src/serverlist.cpp index eee54a3ee..5ad6afe25 100644 --- a/src/serverlist.cpp +++ b/src/serverlist.cpp @@ -37,6 +37,49 @@ along with Freeminer. If not, see . namespace ServerList { +void addMultiProto(Json::Value &server, const u16 port) +{ +#if USE_MULTI + server["proto_multi"]["mt"] = port; +#if USE_SCTP + { + u16 port_multi = 0; + if (!g_settings->getU16NoEx("port_sctp", port_multi)) { + port_multi = port + 100; + } + server["proto_multi"]["sctp"] = port_multi; + } +#endif +#if USE_WEBSOCKET + { + u16 port_multi = 0; + if (!g_settings->getU16NoEx("port_wss", port_multi)) { + port_multi = port; + } + server["proto_multi"]["wss"] = port_multi; + } +#endif +#if USE_WEBSOCKET_SCTP + { + u16 port_multi = 0; + if (!g_settings->getU16NoEx("port_sctp_wss", port_multi)) { + port_multi = port + 100; + } + server["proto_multi"]["sctp_wss"] = port_multi; + } +#endif +#if USE_ENET + { + u16 port_multi = 0; + if (!g_settings->getU16NoEx("port_enet", port_multi)) { + port_multi = port + 200; + } + server["proto_multi"]["enet"] = port_multi; + } +#endif +#endif +} + static const char *aa_names[] = {"start", "update", "delete"}; Json::Value MakeReport(AnnounceAction action, @@ -82,48 +125,7 @@ Json::Value MakeReport(AnnounceAction action, server["gameid"] = gameid; server["proto"] = g_settings->get("server_proto"); - -#if USE_MULTI - server["proto_multi"]["mt"] = port; -#if USE_SCTP - { - u16 port_multi = 0; - if (!g_settings->getU16NoEx("port_sctp", port_multi)) { - port_multi = port + 100; - } - server["proto_multi"]["sctp"] = port_multi; - } -#endif -#if USE_WEBSOCKET - { - u16 port_multi = 0; - if (!g_settings->getU16NoEx("port_wss", port_multi)) { - port_multi = port; - } - server["proto_multi"]["wss"] = port_multi; - } -#endif -#if USE_WEBSOCKET_SCTP - { - u16 port_multi = 0; - if (!g_settings->getU16NoEx("port_sctp_wss", port_multi)) { - port_multi = port + 100; - } - server["proto_multi"]["sctp_wss"] = port_multi; - } -#endif -#if USE_ENET - { - u16 port_multi = 0; - if (!g_settings->getU16NoEx("port_enet", port_multi)) { - port_multi = port + 200; - } - server["proto_multi"]["enet"] = port_multi; - } -#endif -#endif - - + addMultiProto(server, port); } if (action == AA_START) { diff --git a/src/serverlist.h b/src/serverlist.h index b100eccec..ed20d0898 100644 --- a/src/serverlist.h +++ b/src/serverlist.h @@ -37,6 +37,7 @@ namespace ServerList extern lan_adv lan_adv_client; void lan_get(); bool lan_fresh(); + void addMultiProto(Json::Value &server, const u16 port); enum AnnounceAction {AA_START, AA_UPDATE, AA_DELETE}; void sendAnnounce(AnnounceAction, u16 port, diff --git a/util/autotest/auto.pl b/util/autotest/auto.pl index 45adb8dc8..6842831a2 100755 --- a/util/autotest/auto.pl +++ b/util/autotest/auto.pl @@ -75,6 +75,11 @@ $0 ----world_water # stress test of falling sand $0 ----world_sand +# earth +$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 ---cmake_minetest=1 ---build_name=_minetest ----headless ----headless_optimize --address=cool.server.org --port=30001 ---clients_num=25 clients # timelapse video (every 10 seconds) @@ -172,15 +177,13 @@ sub init_config () { # verbose => 1, vtune_amplifier => '~/intel/vtune_amplifier_xe/bin64/', vtune_collect => 'hotspots', # for full list: ~/intel/vtune_amplifier_xe/bin64/amplxe-cl -help collect - world => $script_path . 'world', + #world => $script_path . 'world', world_clear => 0, # remove old world before start client }; map { /^---(\w+)(?:=(.*))?/ and $config->{$1} = defined $2 ? $2 : 1; } @ARGV; map { /^----(\w+)(?:=(.*))?/ and push @{$config->{options_arr}}, $1; } @ARGV; map { /^-D(\w+)(?:=(.*))?/ and $config->{cmake_opt}{$1} = defined $2 ? $2 : 1; } @ARGV; - - $config->{world} = $config->{logdir} . '/world' if $config->{world_local}; } init_config(); @@ -276,7 +279,7 @@ our $options = { mg_params => {"layers" => [{"name" => "default:torch"}, {"name" => "default:glass"}]}, }, world_rooms => { - #--world => $script_path . 'world_rooms', + '--world' => $script_path . 'world_rooms', mg_name => 'math', mg_math => {"generator" => "rooms"}, }, @@ -364,6 +367,15 @@ $commands = { }, build_dir => sub { "$config->{root_prefix}$config->{build_prefix}" . $commands->{build_name}() }, executable => sub { $commands->{build_dir}() . "/" . $config->{executable_name} }, + world_name => sub { + return $config->{world} if defined $config->{world}; + my $name = 'world'; + $name .= '_' . $options->{opt}{mg_name} if $options->{opt}{mg_name}; + $name .= '_' .$config->{config_pass}{mg_math}{generator} if $config->{config_pass}{mg_math}{generator}; + $config->{world} = $script_path . $name; + $config->{world} = $config->{logdir} . '/' . $name if $config->{world_local}; + $config->{world}; + }, init => sub { init_config(); 0 }, '---' => 'init', @@ -379,7 +391,7 @@ $commands = { file_append( "$config->{logdir}/run.sh", join "\n", - qq{# } . join(' ', $0, @ARGV), + qq{# } . join(' ', $0, map{/[\s"]/ ? "'" . $_ . "'" : $_} @ARGV), qq{cd "$build_dir"}, "" ); @@ -408,7 +420,8 @@ $commands = { $D{ENABLE_SCTP} = $config->{cmake_sctp} if defined $config->{cmake_sctp}; $D{USE_LIBCXX} = $config->{cmake_libcxx} if defined $config->{cmake_libcxx}; $D{ENABLE_TOUCH} = $config->{cmake_touch} if defined $config->{cmake_touch}; - $D{USE_GPERF} = $config->{cmake_gperf} if defined $config->{cmake_gperf}; + $D{ENABLE_GPERF} = $config->{cmake_gperf} if defined $config->{cmake_gperf}; + $D{ENABLE_TCMALLOC} = $config->{cmake_tcmalloc} if defined $config->{cmake_tcmalloc}; $D{USE_LTO} = $config->{cmake_lto} if defined $config->{cmake_lto}; $D{EXCEPTION_DEBUG} = $config->{cmake_exception_debug} if defined $config->{cmake_exception_debug}; $D{USE_DEBUG_HELPERS} = 1; @@ -435,6 +448,7 @@ $commands = { }, run_single => sub { sy qq{rm -rf ${root_path}cache/media/* } if $config->{cache_clear} and $root_path; + $commands->{world_name}(); sy qq{rm -rf $config->{world} } if $config->{world_clear} and $config->{world}; return sytee $commands->{env}()