This commit is contained in:
proller committed 2024-05-16 23:21:01 +02:00
1 parent d9d06c27db
commit 2355d7c185
12 files changed
+767 -249

No files matched your search

+1
View File
@@ -1,4 +1,5 @@
ReflowComments: false
BreakStringLiterals: false
BasedOnStyle: LLVM
IndentWidth: 4
+12 -10
View File
@@ -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[]) {
+2 -2
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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);
};
+8 -7
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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) {
+1
View File
@@ -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
View File
@@ -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}()