mirror of
https://github.com/bdnugget/freeminer.git
synced 2026-11-07 06:57:27 +00:00
wip
This commit is contained in:
1 parent
d9d06c27db
commit
2355d7c185
12 files changed
+767
-249
No files matched your search
@@ -1,4 +1,5 @@
|
||||
ReflowComments: false
|
||||
BreakStringLiterals: false
|
||||
|
||||
BasedOnStyle: LLVM
|
||||
IndentWidth: 4
|
||||
|
||||
+12
-10
@@ -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 <execinfo.h> // for backtrace
|
||||
int main(int argc, char *argv[]) {
|
||||
|
||||
@@ -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();
|
||||
|
||||
+2
-2
@@ -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);
|
||||
});
|
||||
}
|
||||
|
||||
+512
-79
@@ -23,6 +23,7 @@ along with Freeminer. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#include "hgt.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cmath>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
@@ -36,12 +37,15 @@ along with Freeminer. If not, see <http://www.gnu.org/licenses/>.
|
||||
#include <string>
|
||||
#include <sys/wait.h>
|
||||
#include <thread>
|
||||
#include <unistd.h>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
#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 <http://www.gnu.org/licenses/>.
|
||||
#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<height_hgt>(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<height_hgt>(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<height_tif>(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<height_gebco_tif>(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<height_tif>(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<height_dummy>();
|
||||
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<height_dummy>();
|
||||
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<std::string> 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<std::tuple<int, int, std::string>>{
|
||||
{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<size_t, size_t, ll_t, ll_t> 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<size_t, size_t, ll_t, ll_t> 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<size_t, size_t, ll_t, ll_t> 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
|
||||
|
||||
+57
-11
@@ -21,6 +21,7 @@ along with Freeminer. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
@@ -30,21 +31,33 @@ along with Freeminer. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
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<int16_t> 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<size_t, size_t, ll_t, ll_t> 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<size_t, size_t, ll_t, ll_t> 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<size_t, size_t, ll_t, ll_t> 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<size_t, size_t, ll_t, ll_t> 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<size_t, size_t, ll_t, ll_t> 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<int, std::map<int, std::unique_ptr<height>>> map;
|
||||
std::map<int, std::map<int, std::shared_ptr<height>>> 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);
|
||||
};
|
||||
@@ -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);
|
||||
|
||||
+102
-80
@@ -23,11 +23,11 @@ along with Freeminer. If not, see <http://www.gnu.org/licenses/>.
|
||||
#include <cstdint>
|
||||
#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<<std::endl;
|
||||
} 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<<std::endl;
|
||||
}
|
||||
|
||||
EXCEPTION_HANDLER_END;
|
||||
}
|
||||
|
||||
+6
-10
@@ -17,23 +17,22 @@ You should have received a copy of the GNU General Public License
|
||||
along with Freeminer. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef FM_LAN_HEADER
|
||||
#define FM_LAN_HEADER
|
||||
#pragma once
|
||||
|
||||
#include <json/value.h>
|
||||
#include <string>
|
||||
#include <atomic>
|
||||
#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
|
||||
+44
-42
@@ -37,6 +37,49 @@ along with Freeminer. If not, see <http://www.gnu.org/licenses/>.
|
||||
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) {
|
||||
|
||||
@@ -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,
|
||||
|
||||
+20
-6
@@ -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}()
|
||||
|
||||
Reference in new issue
Block a user