diff --git a/games/Repixture b/games/Repixture index ee527c47b..473995892 160000 --- a/games/Repixture +++ b/games/Repixture @@ -1 +1 @@ -Subproject commit ee527c47b5422879e0733fe338956e06b3a28515 +Subproject commit 4739958926134d25589a3faab800d7c7af4506e0 diff --git a/games/default b/games/default index 63703a678..f294d421a 160000 --- a/games/default +++ b/games/default @@ -1 +1 @@ -Subproject commit 63703a678345e430cd23a83df4c792de9760f702 +Subproject commit f294d421a8dae3870bcb27fc220e0cd1e12667f2 diff --git a/src/client/fm_farmesh.cpp b/src/client/fm_farmesh.cpp index a9d63759e..1677a6894 100644 --- a/src/client/fm_farmesh.cpp +++ b/src/client/fm_farmesh.cpp @@ -426,8 +426,8 @@ uint8_t FarMesh::update(v3opos_t camera_pos, m_speed = speed; - const auto camera_pos_aligned_int = - playerBlockAlign(*m_control, floatToInt(camera_pos, BS * 16)) * MAP_BLOCKSIZE; + //const auto camera_pos_aligned_int = playerBlockAlign(*m_control, floatToInt(camera_pos, BS * 16)) * MAP_BLOCKSIZE; + const auto camera_pos_aligned_int = floatToInt(camera_pos, BS); // no aligned const auto distance_max = (std::min(render_range, 1.2 * m_client->fog_range / BS) >> 7) << 7; diff --git a/src/client/game.cpp b/src/client/game.cpp index e76b75c73..a0ff6edf6 100644 --- a/src/client/game.cpp +++ b/src/client/game.cpp @@ -4549,21 +4549,23 @@ 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, - //yaw = player->getYaw(), - //pitch = player->getPitch(), - camera_pos = camera->getPosition(), - camera_offset = camera->getOffset(), - speed = player->getSpeed().getLength()]() { - const auto processed = farmesh->update(camera_pos, - //camera->getDirection(), camera->getFovMax(), camera->getCameraMode(), pitch, yaw, - camera_offset, - //sky->getBrightness(), - farmesh_range, speed); - if (!processed) { - std::this_thread::sleep_for(std::chrono::milliseconds(300)); - } - }); + thread_local static uint8_t processed{}; + thread_local static u64 next_run_time{}; + if (processed || porting::getTimeMs() > next_run_time) { + next_run_time = porting::getTimeMs() + 300; + farmesh_async.step([&, farmesh_range = farmesh_range, + //yaw = player->getYaw(), + //pitch = player->getPitch(), + camera_pos = camera->getPosition(), + camera_offset = camera->getOffset(), + speed = player->getSpeed().getLength()]() { + processed = farmesh->update(camera_pos, + //camera->getDirection(), camera->getFovMax(), camera->getCameraMode(), pitch, yaw, + camera_offset, + //sky->getBrightness(), + farmesh_range, speed); + }); + } } /* diff --git a/src/clientiface.cpp b/src/clientiface.cpp index 95c6b359c..2e7ca9b47 100644 --- a/src/clientiface.cpp +++ b/src/clientiface.cpp @@ -514,7 +514,7 @@ void RemoteClient::SetBlocksNotSent(std::map &blocks) */ } -void RemoteClient::SetBlockDeleted(v3bpos_t p) { +void RemoteClient::SetBlockDeleted(const v3bpos_t & p) { m_blocks_sent.erase(p); } diff --git a/src/clientiface.h b/src/clientiface.h index 2c30d22d6..e5834af5b 100644 --- a/src/clientiface.h +++ b/src/clientiface.h @@ -250,27 +250,27 @@ class RemoteClient std::atomic_ushort net_proto_version = 0; // fm: - u16 net_proto_version_fm = 0; + u16 net_proto_version_fm{}; //std::atomic_int m_nearest_unsent_reset {0}; std::atomic_uint wanted_range{10}; - std::atomic_int range_all{0}; - std::atomic_int farmesh = {0}; - float fov = 72; + std::atomic_int range_all{}; + std::atomic_int farmesh = {}; + float fov{72}; //bool block_overflow; - ServerEnvironment *m_env = nullptr; + ServerEnvironment *m_env{}; u32 getSendingCount() const { return 0; } std::map> m_objects_last_pos_sent; v3f m_last_direction; - float m_nearest_unsent_reset_timer; + float m_nearest_unsent_reset_timer{}; std::unordered_map blocks; void SetBlocksNotSent(); - void SetBlockDeleted(v3bpos_t p); - std::vector>> + void SetBlockDeleted(const v3bpos_t &p); + std::vector>> far_blocks_requested{FARMESH_STEP_MAX}; std::mutex far_blocks_requested_mutex; int GetNextBlocksFm(ServerEnvironment *env, EmergeManager *emerge, float dtime, std::vector &dest, double m_uptime, u64 max_ms); - + uint32_t SendFarBlocks(); // == /* Authentication information */ @@ -513,16 +513,7 @@ class ClientInterface { void sendToAll(u16 channelnum, SharedBuffer data, bool reliable); void sendToAll(u16 channelnum, msgpack::sbuffer const &buffer, bool reliable); RemoteClientPtr getClient(u16 peer_id, ClientState state_min = CS_Active); - RemoteClientVector getClientList() { - RemoteClientVector clients; - auto lock = m_clients.lock_unique_rec(); - for(auto & ir : m_clients) { - auto c = ir.second; - if (c) - clients.emplace_back(c); - } - return clients; - } + RemoteClientVector getClientList(); // == diff --git a/src/external/jsoncpp b/src/external/jsoncpp index 5defb4ed1..89e2973c7 160000 --- a/src/external/jsoncpp +++ b/src/external/jsoncpp @@ -1 +1 @@ -Subproject commit 5defb4ed1a4293b8e2bf641e16b156fb9de498cc +Subproject commit 89e2973c754a9c02a49974d839779b151e95afd6 diff --git a/src/fm_clientiface.cpp b/src/fm_clientiface.cpp index 1b2bd939c..299086c67 100644 --- a/src/fm_clientiface.cpp +++ b/src/fm_clientiface.cpp @@ -562,30 +562,41 @@ int RemoteClient::GetNextBlocksFm(ServerEnvironment *env, EmergeManager *emerge, } } + return num_blocks_selected - num_blocks_sending; +} + +uint32_t RemoteClient::SendFarBlocks() +{ + uint16_t sent_cnt{}; TRY_UNIQUE_LOCK(far_blocks_requested_mutex) { std::multimap ordered; - constexpr uint16_t send_max = 50; - uint16_t sent_cnt = 0; + constexpr uint16_t send_max{50}; for (auto &far_blocks : far_blocks_requested) { for (auto &[bpos, step_sent] : far_blocks) { auto &[step, sent_ts] = step_sent; - if (!sent_ts) { + if (sent_ts <= 0) { continue; } if (step >= FARMESH_STEP_MAX - 1) { + sent_ts = -1; continue; } const auto dbase = m_env->m_server->GetFarDatabase(step); if (!dbase) { + sent_ts = -1; continue; } const auto block = m_env->m_server->loadBlockNoStore(dbase, bpos); if (!block) { + sent_ts = -1; continue; } + + g_profiler->add("Server: Far blocks sent", 1); + block->far_step = step; - step_sent.second = 0; + sent_ts = 0; ordered.emplace(sent_ts - step, block); if (++sent_cnt > send_max) { @@ -593,11 +604,26 @@ int RemoteClient::GetNextBlocksFm(ServerEnvironment *env, EmergeManager *emerge, } } } + + // First with larger iteration and smaller step + for (const auto &[key, block] : std::views::reverse(ordered)) { m_env->m_server->SendBlockFm( peer_id, block, serialization_version, net_proto_version); } } + return sent_cnt; +} - return num_blocks_selected - num_blocks_sending; +RemoteClientVector ClientInterface::getClientList() +{ + auto lock = m_clients.lock_unique_rec(); + RemoteClientVector clients; + for (const auto &ir : m_clients) { + const auto &c = ir.second; + if (!c) + continue; + clients.emplace_back(c); + } + return clients; } diff --git a/src/fm_server.cpp b/src/fm_server.cpp index b5ea78944..a93981c76 100644 --- a/src/fm_server.cpp +++ b/src/fm_server.cpp @@ -42,7 +42,46 @@ along with Freeminer. If not, see . #include "debug/stacktrace.h" #include "util/timetaker.h" -ServerThread::ServerThread(Server *server) : thread_vector("Server", 40), m_server(server) +ServerThreadBase::ServerThreadBase(Server *server, const std::string &name, + int priority) : thread_vector{name, 2}, m_server{server} +{ +} + +void *ServerThreadBase::run() +{ + // If something wrong with init order + std::this_thread::sleep_for(std::chrono::milliseconds(sleep_start)); + + BEGIN_DEBUG_EXCEPTION_HANDLER + + auto time_last = porting::getTimeMs(); + + while (!stopRequested()) { + DUMP(""); + try { + const auto time_now = porting::getTimeMs(); + const auto result = step(time_now - time_last); + time_last = time_now; + std::this_thread::sleep_for( + std::chrono::milliseconds(result ? sleep_result : sleep_nothing)); +#if !EXCEPTION_DEBUG + } catch (const std::exception &e) { + errorstream << m_name << ": exception: " << e.what() << std::endl + << stacktrace() << std::endl; + } catch (...) { + errorstream << m_name << ": Unknown unhandled exception at " + << __PRETTY_FUNCTION__ << ":" << __LINE__ << std::endl + << stacktrace() << std::endl; +#else + } catch (int) { // nothing +#endif + } + } + END_DEBUG_EXCEPTION_HANDLER + return nullptr; +} + +ServerThread::ServerThread(Server *server) : thread_vector{"Server", 40}, m_server{server} { } @@ -169,8 +208,18 @@ void *MapThread::run() return nullptr; } +SendFarBlocksThread::SendFarBlocksThread(Server *server) : + ServerThreadBase(server, "SendFarBlocks", 1) +{ +} + +size_t SendFarBlocksThread::step(float dtime) +{ + return m_server->SendFarBlocks(dtime); +} + SendBlocksThread::SendBlocksThread(Server *server) : - thread_vector("SendBlocks", 30), m_server(server) + thread_vector{"SendBlocks", 30}, m_server{server} { } @@ -623,3 +672,15 @@ void Server::SendBlockFm(session_t peer_id, MapBlockP block, u8 ver, auto s = std::string{pkt.getString(0), pkt.getSize()}; Send(&pkt); } + +uint32_t Server::SendFarBlocks(float dtime) +{ + ScopeProfiler sp(g_profiler, "Server send far blocks"); + uint32_t sent{}; + for (const auto &client : m_clients.getClientList()) { + if (!client) + continue; + sent += client->SendFarBlocks(); + } + return sent; +} diff --git a/src/fm_server.h b/src/fm_server.h index f178a3aae..37d97f290 100644 --- a/src/fm_server.h +++ b/src/fm_server.h @@ -25,6 +25,23 @@ along with Freeminer. If not, see . class Server; +class ServerThreadBase : public thread_vector +{ +protected: + Server *const m_server; + +public: + int sleep_start{1000}; + int sleep_result{10}; + int sleep_nothing{1000}; + + ServerThreadBase( + Server *server, const std::string &name = "Unnamed", int priority = 0); + void *run(); + + virtual size_t step(float dtime) = 0; +}; + class ServerThread : public thread_vector { public: @@ -33,12 +50,12 @@ class ServerThread : public thread_vector void *run(); private: - Server *m_server; + Server *const m_server; }; class MapThread : public thread_vector { - Server *m_server; + Server *const m_server; public: MapThread(Server *server); @@ -48,7 +65,7 @@ class MapThread : public thread_vector class SendBlocksThread : public thread_vector { - Server *m_server; + Server *const m_server; public: SendBlocksThread(Server *server); @@ -56,9 +73,19 @@ class SendBlocksThread : public thread_vector void *run(); }; +class SendFarBlocksThread : public ServerThreadBase +{ +public: + //using ServerThreadBase::ServerThreadBase; + SendFarBlocksThread(Server *server); + +private: + size_t step(float dtime) override; +}; + class LiquidThread : public thread_vector { - Server *m_server; + Server *const m_server; public: LiquidThread(Server *server); @@ -68,7 +95,7 @@ class LiquidThread : public thread_vector class EnvThread : public thread_vector { - Server *m_server; + Server *const m_server; public: EnvThread(Server *server); @@ -78,7 +105,7 @@ class EnvThread : public thread_vector class AbmThread : public thread_vector { - Server *m_server; + Server *const m_server; public: AbmThread(Server *server); @@ -88,7 +115,7 @@ class AbmThread : public thread_vector class AbmWorldThread : public thread_vector { - Server *m_server; + Server *const m_server; public: AbmWorldThread(Server *server); @@ -98,7 +125,7 @@ class AbmWorldThread : public thread_vector class WorldMergeThread : public thread_vector { - Server *m_server; + Server *const m_server; public: WorldMergeThread(Server *server); diff --git a/src/server.cpp b/src/server.cpp index 139ded6ac..375cf5a1d 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -451,9 +451,10 @@ void Server::init() if (m_more_threads) { m_map_thread = std::make_unique(this); m_sendblocks_thead = std::make_unique(this); + m_sendfarblocks_thead = std::make_unique(this); m_liquid = std::make_unique(this); m_env_thread = std::make_unique(this); - m_abm_thread = std::make_unique< AbmThread>(this); + m_abm_thread = std::make_unique(this); m_abm_world_thread = std::make_unique(this); m_world_merge_thread = std::make_unique(this); } @@ -604,6 +605,8 @@ void Server::start() m_map_thread->restart(); if (m_sendblocks_thead) m_sendblocks_thead->restart(); + if (m_sendfarblocks_thead) + m_sendfarblocks_thead->restart(); if (m_liquid) m_liquid->restart(); if(m_env_thread) @@ -715,6 +718,8 @@ void Server::stop() m_liquid->stop(); if (m_sendblocks_thead) m_sendblocks_thead->stop(); + if (m_sendfarblocks_thead) + m_sendfarblocks_thead->stop(); if (m_map_thread) m_map_thread->stop(); if(m_abm_thread) @@ -734,6 +739,8 @@ void Server::stop() m_liquid->join(); if (m_sendblocks_thead) m_sendblocks_thead->join(); + if (m_sendfarblocks_thead) + m_sendfarblocks_thead->join(); if (m_map_thread) m_map_thread->join(); if(m_abm_thread) diff --git a/src/server.h b/src/server.h index 3bd66a6a0..6b3c58be1 100644 --- a/src/server.h +++ b/src/server.h @@ -56,6 +56,7 @@ class Circuit; class Stat; class MapThread; class SendBlocksThread; +class SendFarBlocksThread; class LiquidThread; class EnvThread; class AbmThread; @@ -751,49 +752,55 @@ class Server : public con::PeerHandler, public MapEventReceiver, private: int save(float dtime, float dedicated_server_step = 0.1, bool breakable = false); - //fmtodo: remove: + //fmtodo: remove: void DenyAccess(session_t peer_id, const std::string &reason); void SetBlocksNotSent(); void SendFreeminerInit(session_t peer_id, u16 protocol_version); - void SendActiveObjectMessages(session_t peer_id, const ActiveObjectMessages &datas, bool reliable = true); - void SendBlockFm(session_t peer_id, MapBlockP block, u8 ver, u16 net_proto_version, SerializedBlockCache *cache = nullptr); + void SendActiveObjectMessages( + session_t peer_id, const ActiveObjectMessages &datas, bool reliable = true); + void SendBlockFm(session_t peer_id, MapBlockP block, u8 ver, u16 net_proto_version, + SerializedBlockCache *cache = nullptr); - float m_liquid_send_timer = 0 ; - float m_liquid_send_interval = 1; + float m_liquid_send_timer{}; + float m_liquid_send_interval{1}; public: lan_adv lan_adv_server; - int m_autoexit = 0; + int m_autoexit{}; //concurrent_map m_modified_blocks; //concurrent_map m_lighting_modified_blocks; - bool m_more_threads = false; - unsigned int overload = 0; + bool m_more_threads{}; + unsigned int overload{}; - int AsyncRunMapStep(float dtime, float dedicated_server_step = 0.1, bool async=true); + int AsyncRunMapStep( + float dtime, float dedicated_server_step = 0.1, bool async = true); void deleteDetachedInventory(const std::string &name); void maintenance_start(); void maintenance_end(); - int maintenance_status = 0; + int maintenance_status{}; void SendPunchPlayer(session_t peer_id, v3f speed); - void handleCommand_Drawcontrol(NetworkPacket* pkt); - void handleCommand_GetBlocks(NetworkPacket* pkt); - void handleCommand_InitFm(NetworkPacket* pkt); + void handleCommand_Drawcontrol(NetworkPacket *pkt); + void handleCommand_GetBlocks(NetworkPacket *pkt); + void handleCommand_InitFm(NetworkPacket *pkt); std::array, FARMESH_STEP_MAX> far_dbases; - MapDatabase *GetFarDatabase(MapBlock::block_step_t step /*, MapDatabase *zero_db = {}, const std::string &world_path = {}*/); - MapBlockP loadBlockNoStore(MapDatabase *dbase, const v3bpos_t &pos); + MapDatabase *GetFarDatabase(MapBlock::block_step_t + step /*, MapDatabase *zero_db = {}, const std::string &world_path = {}*/); + MapBlockP loadBlockNoStore(MapDatabase *dbase, const v3bpos_t &pos); + uint32_t SendFarBlocks(float dtime); Stat stat; std::unique_ptr m_map_thread; std::unique_ptr m_sendblocks_thead; + std::unique_ptr m_sendfarblocks_thead; std::unique_ptr m_liquid; std::unique_ptr m_env_thread; std::unique_ptr m_abm_thread; std::unique_ptr m_abm_world_thread; std::unique_ptr m_world_merge_thread; -// == + // == // CSM restrictions byteflag u64 m_csm_restriction_flags = CSMRestrictionFlags::CSM_RF_NONE; diff --git a/src/threading/thread_vector.h b/src/threading/thread_vector.h index 0c3bff926..a2b4223c2 100644 --- a/src/threading/thread_vector.h +++ b/src/threading/thread_vector.h @@ -1,7 +1,6 @@ #pragma once #include -#include #include #include #include @@ -38,5 +37,5 @@ class thread_vector protected: std::string m_name; - int m_priority = 0; + int m_priority{}; };