From 8702422943a2b01f8f95159ce4626f2ca74d6fdf Mon Sep 17 00:00:00 2001 From: cvet Date: Thu, 23 May 2024 12:25:00 +0300 Subject: [PATCH 01/12] Using tracy rpmalloc if it's enabled --- BuildTools/FinalizeGeneration.cmake | 5 ++-- BuildTools/StartGeneration.cmake | 2 ++ Source/Common/Common.cpp | 39 +++++++++++++++++------------ 3 files changed, 27 insertions(+), 19 deletions(-) diff --git a/BuildTools/FinalizeGeneration.cmake b/BuildTools/FinalizeGeneration.cmake index 379e0ee11d..5a199d8c87 100644 --- a/BuildTools/FinalizeGeneration.cmake +++ b/BuildTools/FinalizeGeneration.cmake @@ -89,7 +89,7 @@ if(WIN32 OR LINUX OR APPLE OR ANDROID) include_directories("${FO_RPMALLOC_DIR}/rpmalloc") add_library(rpmalloc ${FO_RPMALLOC_SOURCE}) add_compile_definitions(FO_HAVE_RPMALLOC=1) - add_compile_definitions(ENABLE_PRELOAD=1) + add_compile_definitions(ENABLE_PRELOAD=${expr_StandaloneRpmallocEnabled}) target_compile_definitions(rpmalloc PRIVATE "$<$:_GNU_SOURCE>") list(APPEND FO_COMMON_LIBS "rpmalloc") DisableLibWarnings(rpmalloc) @@ -128,10 +128,9 @@ DisableLibWarnings(SDL2main SDL2-static) # Tracy profiler StatusMessage("+ Tracy") set(FO_TRACY_DIR "${FO_ENGINE_ROOT}/ThirdParty/tracy") -set(expr_TracyEnabled $,$,$>) add_compile_definitions($<${expr_TracyEnabled}:TRACY_ENABLE>) add_compile_definitions($<$:TRACY_ON_DEMAND>) -add_compile_definitions(FO_TRACY=$) +add_compile_definitions(FO_TRACY=${expr_TracyEnabled}) set(TRACY_STATIC ON CACHE BOOL "Forced by FOnline" FORCE) add_subdirectory("${FO_TRACY_DIR}") include_directories("${FO_TRACY_DIR}/public") diff --git a/BuildTools/StartGeneration.cmake b/BuildTools/StartGeneration.cmake index 05935762c0..2ce1ffa8af 100644 --- a/BuildTools/StartGeneration.cmake +++ b/BuildTools/StartGeneration.cmake @@ -162,6 +162,8 @@ add_compile_definitions($<$:LLVM_USE_SANITIZER=Add set(expr_FullOptimization $,$,$>) set(expr_DebugInfo $,$,$>>) set(expr_PrefixConfig $,$,$>>) +set(expr_TracyEnabled $,$,$>) +set(expr_StandaloneRpmallocEnabled $) # Headless configuration (without video/audio/input) if(FO_BUILD_CLIENT OR FO_BUILD_SERVER OR FO_BUILD_SINGLE OR FO_BUILD_EDITOR OR FO_BUILD_MAPPER) diff --git a/Source/Common/Common.cpp b/Source/Common/Common.cpp index aa1a6d3255..9e6d8cfa1c 100644 --- a/Source/Common/Common.cpp +++ b/Source/Common/Common.cpp @@ -748,7 +748,13 @@ void emscripten_sleep(unsigned int ms) // Replace memory allocator #if FO_HAVE_RPMALLOC +#if FO_TRACY +#include "client/tracy_rpmalloc.hpp" +#define RPMNS tracy +#else #include "rpmalloc.h" +#define RPMNS +#endif #include @@ -763,7 +769,7 @@ extern void CRTDECL operator delete(void* p) noexcept #if FO_TRACY TracyFree(p); #endif - rpfree(p); + RPMNS::rpfree(p); } extern void CRTDECL operator delete[](void* p) noexcept @@ -771,12 +777,12 @@ extern void CRTDECL operator delete[](void* p) noexcept #if FO_TRACY TracyFree(p); #endif - rpfree(p); + RPMNS::rpfree(p); } extern void* CRTDECL operator new(std::size_t size) noexcept(false) { - auto* p = rpmalloc(size); + auto* p = RPMNS::rpmalloc(size); #if FO_TRACY TracyAlloc(p, size); #endif @@ -785,7 +791,7 @@ extern void* CRTDECL operator new(std::size_t size) noexcept(false) extern void* CRTDECL operator new[](std::size_t size) noexcept(false) { - auto* p = rpmalloc(size); + auto* p = RPMNS::rpmalloc(size); #if FO_TRACY TracyAlloc(p, size); #endif @@ -795,7 +801,7 @@ extern void* CRTDECL operator new[](std::size_t size) noexcept(false) extern void* CRTDECL operator new(std::size_t size, const std::nothrow_t& tag) noexcept { UNUSED_VARIABLE(tag); - auto* p = rpmalloc(size); + auto* p = RPMNS::rpmalloc(size); #if FO_TRACY TracyAlloc(p, size); #endif @@ -805,7 +811,7 @@ extern void* CRTDECL operator new(std::size_t size, const std::nothrow_t& tag) n extern void* CRTDECL operator new[](std::size_t size, const std::nothrow_t& tag) noexcept { UNUSED_VARIABLE(tag); - auto* p = rpmalloc(size); + auto* p = RPMNS::rpmalloc(size); #if FO_TRACY TracyAlloc(p, size); #endif @@ -819,7 +825,7 @@ extern void CRTDECL operator delete(void* p, std::size_t size) noexcept #if FO_TRACY TracyFree(p); #endif - rpfree(p); + RPMNS::rpfree(p); } extern void CRTDECL operator delete[](void* p, std::size_t size) noexcept @@ -828,7 +834,7 @@ extern void CRTDECL operator delete[](void* p, std::size_t size) noexcept #if FO_TRACY TracyFree(p); #endif - rpfree(p); + RPMNS::rpfree(p); } #endif @@ -839,7 +845,7 @@ extern void CRTDECL operator delete(void* p, std::align_val_t align) noexcept #if FO_TRACY TracyFree(p); #endif - rpfree(p); + RPMNS::rpfree(p); } extern void CRTDECL operator delete[](void* p, std::align_val_t align) noexcept @@ -848,7 +854,7 @@ extern void CRTDECL operator delete[](void* p, std::align_val_t align) noexcept #if FO_TRACY TracyFree(p); #endif - rpfree(p); + RPMNS::rpfree(p); } extern void CRTDECL operator delete(void* p, std::size_t size, std::align_val_t align) noexcept @@ -858,7 +864,7 @@ extern void CRTDECL operator delete(void* p, std::size_t size, std::align_val_t #if FO_TRACY TracyFree(p); #endif - rpfree(p); + RPMNS::rpfree(p); } extern void CRTDECL operator delete[](void* p, std::size_t size, std::align_val_t align) noexcept @@ -868,12 +874,12 @@ extern void CRTDECL operator delete[](void* p, std::size_t size, std::align_val_ #if FO_TRACY TracyFree(p); #endif - rpfree(p); + RPMNS::rpfree(p); } extern void* CRTDECL operator new(std::size_t size, std::align_val_t align) noexcept(false) { - auto* p = rpaligned_alloc(static_cast(align), size); + auto* p = RPMNS::rpaligned_alloc(static_cast(align), size); #if FO_TRACY TracyAlloc(p, size); #endif @@ -882,7 +888,7 @@ extern void* CRTDECL operator new(std::size_t size, std::align_val_t align) noex extern void* CRTDECL operator new[](std::size_t size, std::align_val_t align) noexcept(false) { - auto* p = rpaligned_alloc(static_cast(align), size); + auto* p = RPMNS::rpaligned_alloc(static_cast(align), size); #if FO_TRACY TracyAlloc(p, size); #endif @@ -892,7 +898,7 @@ extern void* CRTDECL operator new[](std::size_t size, std::align_val_t align) no extern void* CRTDECL operator new(std::size_t size, std::align_val_t align, const std::nothrow_t& tag) noexcept { UNUSED_VARIABLE(tag); - auto* p = rpaligned_alloc(static_cast(align), size); + auto* p = RPMNS::rpaligned_alloc(static_cast(align), size); #if FO_TRACY TracyAlloc(p, size); #endif @@ -902,7 +908,7 @@ extern void* CRTDECL operator new(std::size_t size, std::align_val_t align, cons extern void* CRTDECL operator new[](std::size_t size, std::align_val_t align, const std::nothrow_t& tag) noexcept { UNUSED_VARIABLE(tag); - auto* p = rpaligned_alloc(static_cast(align), size); + auto* p = RPMNS::rpaligned_alloc(static_cast(align), size); #if FO_TRACY TracyAlloc(p, size); #endif @@ -911,5 +917,6 @@ extern void* CRTDECL operator new[](std::size_t size, std::align_val_t align, co #endif #undef CRTDECL +#undef RPMNS #endif From 3c0bc86db3307322d92814672beac87a8a0217c9 Mon Sep 17 00:00:00 2001 From: cvet Date: Thu, 23 May 2024 14:50:29 +0300 Subject: [PATCH 02/12] GDB correct stop point for break into debugger --- Source/Common/Common.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/Common/Common.cpp b/Source/Common/Common.cpp index 9e6d8cfa1c..a93ccbd7e2 100644 --- a/Source/Common/Common.cpp +++ b/Source/Common/Common.cpp @@ -377,7 +377,7 @@ auto IsRunInDebugger() noexcept -> bool auto BreakIntoDebugger([[maybe_unused]] string_view error_message) noexcept -> bool { - STACK_TRACE_ENTRY(); + NO_STACK_TRACE_ENTRY(); if (IsRunInDebugger()) { #if FO_WINDOWS From 4ff48cacb1b274f33151111fd8d2dd56d9cbc025 Mon Sep 17 00:00:00 2001 From: cvet Date: Wed, 12 Jun 2024 13:47:53 +0300 Subject: [PATCH 03/12] Added GetTalkingCrittersCount --- .../Scripting/ServerCritterScriptMethods.cpp | 14 ++++++++++++++ Source/Server/Critter.cpp | 18 +++--------------- Source/Server/Critter.h | 5 ++--- Source/Server/CritterManager.cpp | 8 ++++---- Source/Server/Server.cpp | 8 ++++---- 5 files changed, 27 insertions(+), 26 deletions(-) diff --git a/Source/Scripting/ServerCritterScriptMethods.cpp b/Source/Scripting/ServerCritterScriptMethods.cpp index 95da9e87f1..7bbae113c2 100644 --- a/Source/Scripting/ServerCritterScriptMethods.cpp +++ b/Source/Scripting/ServerCritterScriptMethods.cpp @@ -459,6 +459,20 @@ return result; } +///@ ExportMethod +[[maybe_unused]] uint Server_Critter_GetTalkingCrittersCount(Critter* self) +{ + uint result = 0; + + for (const auto* cr : self->VisCr) { + if (cr->Talk.Type == TalkType::Critter && cr->Talk.CritterId == self->GetId()) { + result++; + } + } + + return result; +} + ///@ ExportMethod [[maybe_unused]] vector Server_Critter_GetGlobalMapGroupCritters(Critter* self) { diff --git a/Source/Server/Critter.cpp b/Source/Server/Critter.cpp index cd455bbcff..9cb595de87 100644 --- a/Source/Server/Critter.cpp +++ b/Source/Server/Critter.cpp @@ -907,7 +907,7 @@ auto Critter::IsTalking() const -> bool return Talk.Type != TalkType::None; } -auto Critter::GetTalkedPlayers() const -> uint +auto Critter::GetTalkingCritters() const -> uint { STACK_TRACE_ENTRY(); @@ -922,19 +922,7 @@ auto Critter::GetTalkedPlayers() const -> uint return talkers; } -auto Critter::IsTalkedPlayers() const -> bool -{ - STACK_TRACE_ENTRY(); - - for (const auto* cr : VisCr) { - if (cr->Talk.Type == TalkType::Critter && cr->Talk.CritterId == GetId()) { - return true; - } - } - return false; -} - -auto Critter::GetBarterPlayers() const -> uint +auto Critter::GetBarterCritters() const -> uint { STACK_TRACE_ENTRY(); @@ -958,7 +946,7 @@ auto Critter::IsFreeToTalk() const -> bool max_talkers = _engine->Settings.NpcMaxTalkers; } - return GetTalkedPlayers() < max_talkers; + return GetTalkingCritters() < max_talkers; } void Critter::Send_Property(NetProperty type, const Property* prop, const ServerEntity* entity) diff --git a/Source/Server/Critter.h b/Source/Server/Critter.h index 17f3b13af6..cb7252b733 100644 --- a/Source/Server/Critter.h +++ b/Source/Server/Critter.h @@ -101,9 +101,8 @@ class Critter final : public ServerEntity, public EntityWithProto, public Critte [[nodiscard]] auto GetCrFromVisCr(CritterFindType find_type, bool vis_cr_self) -> vector; [[nodiscard]] auto GetGlobalMapCritter(ident_t cr_id) const -> Critter*; [[nodiscard]] auto IsTalking() const -> bool; - [[nodiscard]] auto GetTalkedPlayers() const -> uint; - [[nodiscard]] auto IsTalkedPlayers() const -> bool; - [[nodiscard]] auto GetBarterPlayers() const -> uint; + [[nodiscard]] auto GetTalkingCritters() const -> uint; + [[nodiscard]] auto GetBarterCritters() const -> uint; [[nodiscard]] auto IsFreeToTalk() const -> bool; [[nodiscard]] auto IsMoving() const -> bool { return !Moving.Steps.empty(); } diff --git a/Source/Server/CritterManager.cpp b/Source/Server/CritterManager.cpp index 70f8d6535c..9229a588c8 100644 --- a/Source/Server/CritterManager.cpp +++ b/Source/Server/CritterManager.cpp @@ -472,11 +472,11 @@ void CritterManager::CloseTalk(Critter* cr) talker = GetCritter(cr->Talk.CritterId); if (talker != nullptr) { if (cr->Talk.Barter) { - talker->OnBarter.Fire(cr, false, talker->GetBarterPlayers()); - _engine->OnCritterBarter.Fire(talker, cr, false, talker->GetBarterPlayers()); + talker->OnBarter.Fire(cr, false, talker->GetBarterCritters()); + _engine->OnCritterBarter.Fire(talker, cr, false, talker->GetBarterCritters()); } - talker->OnTalk.Fire(cr, false, talker->GetTalkedPlayers()); - _engine->OnCritterTalk.Fire(talker, cr, false, talker->GetTalkedPlayers()); + talker->OnTalk.Fire(cr, false, talker->GetTalkingCritters()); + _engine->OnCritterTalk.Fire(talker, cr, false, talker->GetTalkingCritters()); } } diff --git a/Source/Server/Server.cpp b/Source/Server/Server.cpp index a2636f28a2..82631e6969 100644 --- a/Source/Server/Server.cpp +++ b/Source/Server/Server.cpp @@ -4247,7 +4247,7 @@ void FOServer::BeginDialog(Critter* cl, Critter* npc, hstring dlg_pack_id, uint1 // Todo: don't remeber but need check (IsPlaneNoTalk) - if (!npc->OnTalk.Fire(cl, true, npc->GetTalkedPlayers() + 1) || !OnCritterTalk.Fire(npc, cl, true, npc->GetTalkedPlayers() + 1)) { + if (!npc->OnTalk.Fire(cl, true, npc->GetTalkingCritters() + 1) || !OnCritterTalk.Fire(npc, cl, true, npc->GetTalkingCritters() + 1)) { return; } @@ -4454,7 +4454,7 @@ void FOServer::Process_Dialog(Player* player) return; } - if (!talker->OnBarter.Fire(cr, true, talker->GetBarterPlayers() + 1) || !OnCritterBarter.Fire(talker, cr, true, talker->GetBarterPlayers() + 1)) { + if (!talker->OnBarter.Fire(cr, true, talker->GetBarterCritters() + 1) || !OnCritterBarter.Fire(talker, cr, true, talker->GetBarterCritters() + 1)) { cr->Talk.Barter = true; cr->Talk.StartTime = GameTime.GameplayTime(); cr->Talk.TalkTime = std::chrono::milliseconds {Settings.DlgBarterMaxTime}; @@ -4529,8 +4529,8 @@ void FOServer::Process_Dialog(Player* player) cr->Talk.Barter = false; next_dlg_id = cur_dialog->Id; if (talker != nullptr) { - talker->OnBarter.Fire(cr, false, talker->GetBarterPlayers() + 1); - OnCritterBarter.Fire(talker, cr, false, talker->GetBarterPlayers() + 1); + talker->OnBarter.Fire(cr, false, talker->GetBarterCritters() + 1); + OnCritterBarter.Fire(talker, cr, false, talker->GetBarterCritters() + 1); } } From 486fb31cd6eb2085b842faba78f80d9dcf1953db Mon Sep 17 00:00:00 2001 From: cvet Date: Thu, 13 Jun 2024 16:40:23 +0300 Subject: [PATCH 04/12] OnCritterTalk/OnCritterBarter args fix --- Source/Server/Server.cpp | 6 +++--- Source/Server/Server.h | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Source/Server/Server.cpp b/Source/Server/Server.cpp index 82631e6969..c0403254b0 100644 --- a/Source/Server/Server.cpp +++ b/Source/Server/Server.cpp @@ -4247,7 +4247,7 @@ void FOServer::BeginDialog(Critter* cl, Critter* npc, hstring dlg_pack_id, uint1 // Todo: don't remeber but need check (IsPlaneNoTalk) - if (!npc->OnTalk.Fire(cl, true, npc->GetTalkingCritters() + 1) || !OnCritterTalk.Fire(npc, cl, true, npc->GetTalkingCritters() + 1)) { + if (!npc->OnTalk.Fire(cl, true, npc->GetTalkingCritters() + 1) || !OnCritterTalk.Fire(cl, npc, true, npc->GetTalkingCritters() + 1)) { return; } @@ -4454,7 +4454,7 @@ void FOServer::Process_Dialog(Player* player) return; } - if (!talker->OnBarter.Fire(cr, true, talker->GetBarterCritters() + 1) || !OnCritterBarter.Fire(talker, cr, true, talker->GetBarterCritters() + 1)) { + if (!talker->OnBarter.Fire(cr, true, talker->GetBarterCritters() + 1) || !OnCritterBarter.Fire(cr, talker, true, talker->GetBarterCritters() + 1)) { cr->Talk.Barter = true; cr->Talk.StartTime = GameTime.GameplayTime(); cr->Talk.TalkTime = std::chrono::milliseconds {Settings.DlgBarterMaxTime}; @@ -4530,7 +4530,7 @@ void FOServer::Process_Dialog(Player* player) next_dlg_id = cur_dialog->Id; if (talker != nullptr) { talker->OnBarter.Fire(cr, false, talker->GetBarterCritters() + 1); - OnCritterBarter.Fire(talker, cr, false, talker->GetBarterCritters() + 1); + OnCritterBarter.Fire(cr, talker, false, talker->GetBarterCritters() + 1); } } diff --git a/Source/Server/Server.h b/Source/Server/Server.h index 401605ad38..bc48856f4f 100644 --- a/Source/Server/Server.h +++ b/Source/Server/Server.h @@ -166,9 +166,9 @@ class FOServer : virtual public FOEngineBase ///@ ExportEvent ENTITY_EVENT(OnCritterMoveItem, Critter* /*cr*/, Item* /*item*/, CritterItemSlot /*fromSlot*/); ///@ ExportEvent - ENTITY_EVENT(OnCritterTalk, Critter* /*cr*/, Critter* /*playerCr*/, bool /*begin*/, uint /*talkers*/); + ENTITY_EVENT(OnCritterTalk, Critter* /*cr*/, Critter* /*talker*/, bool /*begin*/, uint /*talkers*/); ///@ ExportEvent - ENTITY_EVENT(OnCritterBarter, Critter* /*cr*/, Critter* /*playerCr*/, bool /*begin*/, uint /*barterCount*/); + ENTITY_EVENT(OnCritterBarter, Critter* /*cr*/, Critter* /*trader*/, bool /*begin*/, uint /*barterCount*/); ///@ ExportEvent ENTITY_EVENT(OnCritterGetAttackDistantion, Critter* /*cr*/, AbstractItem* /*item*/, uint8 /*itemMode*/, uint& /*dist*/); ///@ ExportEvent From faa9e46a71c1a72c4f5e768f839b1f55a149640c Mon Sep 17 00:00:00 2001 From: cvet Date: Thu, 13 Jun 2024 17:15:19 +0300 Subject: [PATCH 05/12] OnCritterTalk/OnCritterBarter args fix --- Source/Server/CritterManager.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Source/Server/CritterManager.cpp b/Source/Server/CritterManager.cpp index 9229a588c8..e788917cb3 100644 --- a/Source/Server/CritterManager.cpp +++ b/Source/Server/CritterManager.cpp @@ -473,10 +473,10 @@ void CritterManager::CloseTalk(Critter* cr) if (talker != nullptr) { if (cr->Talk.Barter) { talker->OnBarter.Fire(cr, false, talker->GetBarterCritters()); - _engine->OnCritterBarter.Fire(talker, cr, false, talker->GetBarterCritters()); + _engine->OnCritterBarter.Fire(cr, talker, false, talker->GetBarterCritters()); } talker->OnTalk.Fire(cr, false, talker->GetTalkingCritters()); - _engine->OnCritterTalk.Fire(talker, cr, false, talker->GetTalkingCritters()); + _engine->OnCritterTalk.Fire(cr, talker, false, talker->GetTalkingCritters()); } } From f71b653b49ca21db312e79d60ec03852d07e0b1c Mon Sep 17 00:00:00 2001 From: cvet Date: Thu, 13 Jun 2024 20:38:08 +0300 Subject: [PATCH 06/12] Force tracy InitRpmalloc --- Source/Common/Common.cpp | 75 ++++++++++++++++++++++++++++++---------- 1 file changed, 56 insertions(+), 19 deletions(-) diff --git a/Source/Common/Common.cpp b/Source/Common/Common.cpp index a93ccbd7e2..8a9c6e48b7 100644 --- a/Source/Common/Common.cpp +++ b/Source/Common/Common.cpp @@ -750,10 +750,8 @@ void emscripten_sleep(unsigned int ms) #if FO_TRACY #include "client/tracy_rpmalloc.hpp" -#define RPMNS tracy #else #include "rpmalloc.h" -#define RPMNS #endif #include @@ -768,32 +766,42 @@ extern void CRTDECL operator delete(void* p) noexcept { #if FO_TRACY TracyFree(p); + tracy::rpfree(p); +#else + rpfree(p); #endif - RPMNS::rpfree(p); } extern void CRTDECL operator delete[](void* p) noexcept { #if FO_TRACY TracyFree(p); + tracy::rpfree(p); +#else + rpfree(p); #endif - RPMNS::rpfree(p); } extern void* CRTDECL operator new(std::size_t size) noexcept(false) { - auto* p = RPMNS::rpmalloc(size); #if FO_TRACY + tracy::InitRpmalloc(); + auto* p = tracy::rpmalloc(size); TracyAlloc(p, size); +#else + auto* p = rpmalloc(size); #endif return p; } extern void* CRTDECL operator new[](std::size_t size) noexcept(false) { - auto* p = RPMNS::rpmalloc(size); #if FO_TRACY + tracy::InitRpmalloc(); + auto* p = tracy::rpmalloc(size); TracyAlloc(p, size); +#else + auto* p = rpmalloc(size); #endif return p; } @@ -801,9 +809,12 @@ extern void* CRTDECL operator new[](std::size_t size) noexcept(false) extern void* CRTDECL operator new(std::size_t size, const std::nothrow_t& tag) noexcept { UNUSED_VARIABLE(tag); - auto* p = RPMNS::rpmalloc(size); #if FO_TRACY + tracy::InitRpmalloc(); + auto* p = tracy::rpmalloc(size); TracyAlloc(p, size); +#else + auto* p = rpmalloc(size); #endif return p; } @@ -811,9 +822,12 @@ extern void* CRTDECL operator new(std::size_t size, const std::nothrow_t& tag) n extern void* CRTDECL operator new[](std::size_t size, const std::nothrow_t& tag) noexcept { UNUSED_VARIABLE(tag); - auto* p = RPMNS::rpmalloc(size); #if FO_TRACY + tracy::InitRpmalloc(); + auto* p = tracy::rpmalloc(size); TracyAlloc(p, size); +#else + auto* p = rpmalloc(size); #endif return p; } @@ -824,8 +838,10 @@ extern void CRTDECL operator delete(void* p, std::size_t size) noexcept UNUSED_VARIABLE(size); #if FO_TRACY TracyFree(p); + tracy::rpfree(p); +#else + rpfree(p); #endif - RPMNS::rpfree(p); } extern void CRTDECL operator delete[](void* p, std::size_t size) noexcept @@ -833,8 +849,10 @@ extern void CRTDECL operator delete[](void* p, std::size_t size) noexcept UNUSED_VARIABLE(size); #if FO_TRACY TracyFree(p); + tracy::rpfree(p); +#else + rpfree(p); #endif - RPMNS::rpfree(p); } #endif @@ -844,8 +862,10 @@ extern void CRTDECL operator delete(void* p, std::align_val_t align) noexcept UNUSED_VARIABLE(align); #if FO_TRACY TracyFree(p); + tracy::rpfree(p); +#else + rpfree(p); #endif - RPMNS::rpfree(p); } extern void CRTDECL operator delete[](void* p, std::align_val_t align) noexcept @@ -853,8 +873,10 @@ extern void CRTDECL operator delete[](void* p, std::align_val_t align) noexcept UNUSED_VARIABLE(align); #if FO_TRACY TracyFree(p); + tracy::rpfree(p); +#else + rpfree(p); #endif - RPMNS::rpfree(p); } extern void CRTDECL operator delete(void* p, std::size_t size, std::align_val_t align) noexcept @@ -863,8 +885,10 @@ extern void CRTDECL operator delete(void* p, std::size_t size, std::align_val_t UNUSED_VARIABLE(align); #if FO_TRACY TracyFree(p); + tracy::rpfree(p); +#else + rpfree(p); #endif - RPMNS::rpfree(p); } extern void CRTDECL operator delete[](void* p, std::size_t size, std::align_val_t align) noexcept @@ -873,24 +897,32 @@ extern void CRTDECL operator delete[](void* p, std::size_t size, std::align_val_ UNUSED_VARIABLE(align); #if FO_TRACY TracyFree(p); + tracy::rpfree(p); +#else + rpfree(p); #endif - RPMNS::rpfree(p); } extern void* CRTDECL operator new(std::size_t size, std::align_val_t align) noexcept(false) { - auto* p = RPMNS::rpaligned_alloc(static_cast(align), size); #if FO_TRACY + tracy::InitRpmalloc(); + auto* p = tracy::rpaligned_alloc(static_cast(align), size); TracyAlloc(p, size); +#else + auto* p = rpaligned_alloc(static_cast(align), size); #endif return p; } extern void* CRTDECL operator new[](std::size_t size, std::align_val_t align) noexcept(false) { - auto* p = RPMNS::rpaligned_alloc(static_cast(align), size); #if FO_TRACY + tracy::InitRpmalloc(); + auto* p = tracy::rpaligned_alloc(static_cast(align), size); TracyAlloc(p, size); +#else + auto* p = rpaligned_alloc(static_cast(align), size); #endif return p; } @@ -898,9 +930,12 @@ extern void* CRTDECL operator new[](std::size_t size, std::align_val_t align) no extern void* CRTDECL operator new(std::size_t size, std::align_val_t align, const std::nothrow_t& tag) noexcept { UNUSED_VARIABLE(tag); - auto* p = RPMNS::rpaligned_alloc(static_cast(align), size); #if FO_TRACY + tracy::InitRpmalloc(); + auto* p = tracy::rpaligned_alloc(static_cast(align), size); TracyAlloc(p, size); +#else + auto* p = rpaligned_alloc(static_cast(align), size); #endif return p; } @@ -908,15 +943,17 @@ extern void* CRTDECL operator new(std::size_t size, std::align_val_t align, cons extern void* CRTDECL operator new[](std::size_t size, std::align_val_t align, const std::nothrow_t& tag) noexcept { UNUSED_VARIABLE(tag); - auto* p = RPMNS::rpaligned_alloc(static_cast(align), size); #if FO_TRACY + tracy::InitRpmalloc(); + auto* p = tracy::rpaligned_alloc(static_cast(align), size); TracyAlloc(p, size); +#else + auto* p = rpaligned_alloc(static_cast(align), size); #endif return p; } #endif #undef CRTDECL -#undef RPMNS #endif From daecc3557d9e19b8f10441a4e4464bbd3dd6f195 Mon Sep 17 00:00:00 2001 From: cvet Date: Fri, 14 Jun 2024 11:30:08 +0300 Subject: [PATCH 07/12] LookDistance VirtualProtected -> Protected --- Source/Common/EntityProperties.h | 2 +- Source/Scripting/ServerMapScriptMethods.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Source/Common/EntityProperties.h b/Source/Common/EntityProperties.h index 2300d2dd63..6ab53637e2 100644 --- a/Source/Common/EntityProperties.h +++ b/Source/Common/EntityProperties.h @@ -333,7 +333,7 @@ class CritterProperties : public EntityProperties ///@ ExportProperty ENTITY_PROPERTY(VirtualPrivateServer, uint, SneakCoefficient); ///@ ExportProperty - ENTITY_PROPERTY(VirtualProtected, uint, LookDistance); + ENTITY_PROPERTY(Protected, uint, LookDistance); ///@ ExportProperty ENTITY_PROPERTY(Protected, int, ReplicationTime); ///@ ExportProperty diff --git a/Source/Scripting/ServerMapScriptMethods.cpp b/Source/Scripting/ServerMapScriptMethods.cpp index b960af1bcd..fe5468e672 100644 --- a/Source/Scripting/ServerMapScriptMethods.cpp +++ b/Source/Scripting/ServerMapScriptMethods.cpp @@ -1291,7 +1291,7 @@ } for (Critter* cr : self->GetPlayerCritters()) { - if (self->GetEngine()->Geometry.CheckDist(hx, hy, cr->GetHexX(), cr->GetHexY(), (radius == 0 ? cr->GetLookDistance() : radius) + cr->GetMultihex())) { + if (GeometryHelper::CheckDist(hx, hy, cr->GetHexX(), cr->GetHexY(), (radius == 0 ? cr->GetLookDistance() : radius) + cr->GetMultihex())) { cr->Send_PlaySound(ident_t {}, soundName); } } From 3526022f1a119501daf08a891a9b86c011cac2cf Mon Sep 17 00:00:00 2001 From: cvet Date: Fri, 14 Jun 2024 11:38:37 +0300 Subject: [PATCH 08/12] LookDistance VirtualPrivateServer -> PrivateServer --- Source/Common/EntityProperties.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/Common/EntityProperties.h b/Source/Common/EntityProperties.h index 6ab53637e2..916a7965cf 100644 --- a/Source/Common/EntityProperties.h +++ b/Source/Common/EntityProperties.h @@ -331,7 +331,7 @@ class CritterProperties : public EntityProperties ///@ ExportProperty ReadOnly ENTITY_PROPERTY(PrivateServer, vector, GlobalMapFog); ///@ ExportProperty - ENTITY_PROPERTY(VirtualPrivateServer, uint, SneakCoefficient); + ENTITY_PROPERTY(PrivateServer, uint, SneakCoefficient); ///@ ExportProperty ENTITY_PROPERTY(Protected, uint, LookDistance); ///@ ExportProperty From d284634615b61d8a14c690047879b5bf71989041 Mon Sep 17 00:00:00 2001 From: cvet Date: Fri, 14 Jun 2024 13:43:54 +0300 Subject: [PATCH 09/12] Server path find - skip small stack trace entries --- Source/Server/Map.cpp | 29 ++++++++++++++++------------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/Source/Server/Map.cpp b/Source/Server/Map.cpp index 590018480c..d0884c53ec 100644 --- a/Source/Server/Map.cpp +++ b/Source/Server/Map.cpp @@ -488,7 +488,7 @@ void Map::SendProperty(NetProperty type, const Property* prop, ServerEntity* ent auto Map::IsHexMovable(uint16 hx, uint16 hy) const -> bool { - STACK_TRACE_ENTRY(); + NO_STACK_TRACE_ENTRY(); const auto& field = _hexField.GetCellForReading(hx, hy); const auto& static_field = _staticMap->HexField.GetCellForReading(hx, hy); @@ -498,7 +498,7 @@ auto Map::IsHexMovable(uint16 hx, uint16 hy) const -> bool auto Map::IsHexShootable(uint16 hx, uint16 hy) const -> bool { - STACK_TRACE_ENTRY(); + NO_STACK_TRACE_ENTRY(); const auto& field = _hexField.GetCellForReading(hx, hy); const auto& static_field = _staticMap->HexField.GetCellForReading(hx, hy); @@ -508,7 +508,7 @@ auto Map::IsHexShootable(uint16 hx, uint16 hy) const -> bool auto Map::IsHexesMovable(uint16 hx, uint16 hy, uint radius) const -> bool { - STACK_TRACE_ENTRY(); + NO_STACK_TRACE_ENTRY(); // Base if (!IsHexMovable(hx, hy)) { @@ -538,10 +538,11 @@ auto Map::IsHexesMovable(uint16 hx, uint16 hy, uint radius) const -> bool auto Map::IsHexesMovable(uint16 to_hx, uint16 to_hy, uint radius, Critter* skip_cr) -> bool { - STACK_TRACE_ENTRY(); + NO_STACK_TRACE_ENTRY(); if (_engine->Settings.CritterBlockHex) { if (skip_cr != nullptr && !skip_cr->IsDead()) { + // Todo: make movable checks without critter removing RemoveCritterFromField(skip_cr); const auto result = IsHexesMovable(to_hx, to_hy, radius); AddCritterToField(skip_cr); @@ -634,7 +635,7 @@ void Map::AnimateItem(Item* item, hstring anim_name, bool looped, bool reversed) auto Map::IsBlockItem(uint16 hx, uint16 hy) const -> bool { - STACK_TRACE_ENTRY(); + NO_STACK_TRACE_ENTRY(); const auto& field = _hexField.GetCellForReading(hx, hy); @@ -643,7 +644,7 @@ auto Map::IsBlockItem(uint16 hx, uint16 hy) const -> bool auto Map::IsItemTrigger(uint16 hx, uint16 hy) const -> bool { - STACK_TRACE_ENTRY(); + NO_STACK_TRACE_ENTRY(); const auto& field = _hexField.GetCellForReading(hx, hy); @@ -652,7 +653,7 @@ auto Map::IsItemTrigger(uint16 hx, uint16 hy) const -> bool auto Map::IsItemGag(uint16 hx, uint16 hy) const -> bool { - STACK_TRACE_ENTRY(); + NO_STACK_TRACE_ENTRY(); const auto& field = _hexField.GetCellForReading(hx, hy); @@ -716,7 +717,7 @@ auto Map::GetItems(uint16 hx, uint16 hy) -> const vector& NON_CONST_METHOD_HINT(); - auto& field = _hexField.GetCellForReading(hx, hy); + const auto& field = _hexField.GetCellForReading(hx, hy); return field.Items; } @@ -895,7 +896,7 @@ void Map::SetHexManualBlock(uint16 hx, uint16 hy, bool enable, bool full) auto Map::IsAnyCritter(uint16 hx, uint16 hy) const -> bool { - STACK_TRACE_ENTRY(); + NO_STACK_TRACE_ENTRY(); const auto& field = _hexField.GetCellForReading(hx, hy); @@ -904,7 +905,7 @@ auto Map::IsAnyCritter(uint16 hx, uint16 hy) const -> bool auto Map::IsNonDeadCritter(uint16 hx, uint16 hy) const -> bool { - STACK_TRACE_ENTRY(); + NO_STACK_TRACE_ENTRY(); const auto& field = _hexField.GetCellForReading(hx, hy); @@ -913,7 +914,7 @@ auto Map::IsNonDeadCritter(uint16 hx, uint16 hy) const -> bool auto Map::IsDeadCritter(uint16 hx, uint16 hy) const -> bool { - STACK_TRACE_ENTRY(); + NO_STACK_TRACE_ENTRY(); const auto& field = _hexField.GetCellForReading(hx, hy); @@ -922,7 +923,7 @@ auto Map::IsDeadCritter(uint16 hx, uint16 hy) const -> bool auto Map::IsCritter(uint16 hx, uint16 hy, const Critter* cr) const -> bool { - STACK_TRACE_ENTRY(); + NO_STACK_TRACE_ENTRY(); RUNTIME_ASSERT(cr); @@ -960,6 +961,8 @@ auto Map::GetNonDeadCritter(uint16 hx, uint16 hy) -> Critter* { STACK_TRACE_ENTRY(); + NON_CONST_METHOD_HINT(); + const auto& field = _hexField.GetCellForReading(hx, hy); if (field.IsNonDeadCritter) { @@ -1147,7 +1150,7 @@ void Map::SetTextMsgLex(uint16 hx, uint16 hy, ucolor color, TextPackName text_pa auto Map::IsStaticItemTrigger(uint16 hx, uint16 hy) const -> bool { - STACK_TRACE_ENTRY(); + NO_STACK_TRACE_ENTRY(); const auto& static_field = _staticMap->HexField.GetCellForReading(hx, hy); From 8338c151454dbdc4183fd4ba136a308e68c1c765 Mon Sep 17 00:00:00 2001 From: cvet Date: Fri, 14 Jun 2024 15:03:23 +0300 Subject: [PATCH 10/12] Configuration name Profiling -> Profiling_Total --- BuildTools/FinalizeGeneration.cmake | 2 +- BuildTools/StartGeneration.cmake | 8 +++++--- BuildTools/package.py | 12 ++++++------ Source/Server/Map.cpp | 1 + 4 files changed, 13 insertions(+), 10 deletions(-) diff --git a/BuildTools/FinalizeGeneration.cmake b/BuildTools/FinalizeGeneration.cmake index 5a199d8c87..4662ccfe64 100644 --- a/BuildTools/FinalizeGeneration.cmake +++ b/BuildTools/FinalizeGeneration.cmake @@ -129,7 +129,7 @@ DisableLibWarnings(SDL2main SDL2-static) StatusMessage("+ Tracy") set(FO_TRACY_DIR "${FO_ENGINE_ROOT}/ThirdParty/tracy") add_compile_definitions($<${expr_TracyEnabled}:TRACY_ENABLE>) -add_compile_definitions($<$:TRACY_ON_DEMAND>) +add_compile_definitions($<${expr_TracyOnDemand}:TRACY_ON_DEMAND>) add_compile_definitions(FO_TRACY=${expr_TracyEnabled}) set(TRACY_STATIC ON CACHE BOOL "Forced by FOnline" FORCE) add_subdirectory("${FO_TRACY_DIR}") diff --git a/BuildTools/StartGeneration.cmake b/BuildTools/StartGeneration.cmake index 2ce1ffa8af..b5c2245fc9 100644 --- a/BuildTools/StartGeneration.cmake +++ b/BuildTools/StartGeneration.cmake @@ -116,9 +116,10 @@ if(FO_MULTICONFIG) set(CMAKE_CONFIGURATION_TYPES ${FO_CONFIGURATION_TYPES} CACHE STRING "Forced by FOnline" FORCE) endif() -AddConfiguration(Profiling RelWithDebInfo) +AddConfiguration(Profiling_Total RelWithDebInfo) AddConfiguration(Profiling_OnDemand RelWithDebInfo) -AddConfiguration(Debug_Profiling Debug) +AddConfiguration(Debug_Profiling_Total Debug) +AddConfiguration(Debug_Profiling_OnDemand Debug) AddConfiguration(Release_Ext Release) if(CMAKE_CXX_COMPILER_ID STREQUAL "Clang") @@ -162,7 +163,8 @@ add_compile_definitions($<$:LLVM_USE_SANITIZER=Add set(expr_FullOptimization $,$,$>) set(expr_DebugInfo $,$,$>>) set(expr_PrefixConfig $,$,$>>) -set(expr_TracyEnabled $,$,$>) +set(expr_TracyEnabled $,$,$,$>) +set(expr_TracyOnDemand $,$>) set(expr_StandaloneRpmallocEnabled $) # Headless configuration (without video/audio/input) diff --git a/BuildTools/package.py b/BuildTools/package.py index 8a8bfecc41..0611dd3ac9 100644 --- a/BuildTools/package.py +++ b/BuildTools/package.py @@ -223,16 +223,16 @@ def patchConfig(filePath, additionalConfigData=None): for binType in [''] + \ (['Headless'] if 'Headless' in packArgs else []) + \ (['Service'] if 'Service' in packArgs else []) + \ - (['Profiling'] if 'Profiling' in packArgs else []) + \ + (['TotalProfiling'] if 'TotalProfiling' in packArgs else []) + \ (['OnDemandProfiling'] if 'OnDemandProfiling' in packArgs else []) + \ (['OGL'] if 'OGL' in packArgs else []): binName = args.devname + '_' + args.target + (binType if binType in ['Headless', 'Service'] else '') binOutName = (binName if args.target != 'Client' else args.nicename) + \ - ('_Profiling' if binType in ['Profiling', 'OnDemandProfiling'] else '') + \ + ('_Profiling' if binType in ['TotalProfiling', 'OnDemandProfiling'] else '') + \ ('_OpenGL' if binType == 'OGL' else '') log('Setup', arch, binName, binType) binEntry = args.target + '-' + args.platform + '-' + arch + \ - ('-Profiling' if binType == 'Profiling' else '') + \ + ('-Profiling_Total' if binType == 'TotalProfiling' else '') + \ ('-Profiling_OnDemand' if binType == 'OnDemandProfiling' else '') + \ ('-Debug' if 'Debug' in packArgs else '') binPath = getInput(os.path.join('Binaries', binEntry), binName) @@ -336,14 +336,14 @@ def patchConfig(filePath, additionalConfigData=None): for binType in [''] + \ (['Headless'] if 'Headless' in packArgs else []) + \ (['Daemon'] if 'Daemon' in packArgs else []) + \ - (['Profiling'] if 'Profiling' in packArgs else []) + \ + (['TotalProfiling'] if 'TotalProfiling' in packArgs else []) + \ (['OnDemandProfiling'] if 'OnDemandProfiling' in packArgs else []): binName = args.devname + '_' + args.target + (binType if binType in ['Headless', 'Daemon'] else '') binOutName = (binName if args.target != 'Client' else args.nicename) + \ - ('_Profiling' if binType in ['Profiling', 'OnDemandProfiling'] else '') + ('_Profiling' if binType in ['TotalProfiling', 'OnDemandProfiling'] else '') log('Setup', arch, binName, binType) binEntry = args.target + '-' + args.platform + '-' + arch + \ - ('-Profiling' if binType == 'Profiling' else '') + \ + ('-Profiling_Total' if binType == 'TotalProfiling' else '') + \ ('-Profiling_OnDemand' if binType == 'OnDemandProfiling' else '') + \ ('-Debug' if 'Debug' in packArgs else '') binPath = getInput(os.path.join('Binaries', binEntry), binName) diff --git a/Source/Server/Map.cpp b/Source/Server/Map.cpp index d0884c53ec..c5b7202b8d 100644 --- a/Source/Server/Map.cpp +++ b/Source/Server/Map.cpp @@ -1183,6 +1183,7 @@ auto Map::GetStaticItem(uint16 hx, uint16 hy, hstring pid) -> StaticItem* return item; } } + return nullptr; } From 6a7d51c1c99944d015d2df9243255bdd8f15f76d Mon Sep 17 00:00:00 2001 From: cvet Date: Fri, 14 Jun 2024 15:59:22 +0300 Subject: [PATCH 11/12] Server maps static/dynamic grid now resolved at runtime --- Source/Common/Settings-Include.h | 2 + Source/Common/TwoDimensionalGrid.h | 159 +++++++++++++++++++++++++++++ Source/Server/Map.cpp | 67 ++++++------ Source/Server/Map.h | 4 +- Source/Server/MapManager.cpp | 19 ++-- 5 files changed, 211 insertions(+), 40 deletions(-) diff --git a/Source/Common/Settings-Include.h b/Source/Common/Settings-Include.h index 204bcd8a43..d7c4229eab 100644 --- a/Source/Common/Settings-Include.h +++ b/Source/Common/Settings-Include.h @@ -334,6 +334,8 @@ FIXED_SETTING(uint, DataBaseCommitPeriod, 10); FIXED_SETTING(uint, DataBaseMaxCommitJobs, 100); FIXED_SETTING(uint, LoopAverageTimeInterval, 1000); FIXED_SETTING(bool, WriteHealthFile, false); +FIXED_SETTING(bool, ProtoMapStaticGrid, false); +FIXED_SETTING(bool, MapInstanceStaticGrid, false); SETTING_GROUP_END(); #undef FIXED_SETTING diff --git a/Source/Common/TwoDimensionalGrid.h b/Source/Common/TwoDimensionalGrid.h index 4c9d07cb72..a06e653bee 100644 --- a/Source/Common/TwoDimensionalGrid.h +++ b/Source/Common/TwoDimensionalGrid.h @@ -35,6 +35,165 @@ #include "Common.h" +template +class BaseTwoDimensionalGrid +{ +public: + BaseTwoDimensionalGrid(TIndex width, TIndex height) + { + STACK_TRACE_ENTRY(); + + if constexpr (std::is_signed_v) { + RUNTIME_ASSERT(width >= 0); + RUNTIME_ASSERT(height >= 0); + } + + _width = width; + _height = height; + } + + BaseTwoDimensionalGrid(const BaseTwoDimensionalGrid&) = default; + BaseTwoDimensionalGrid(BaseTwoDimensionalGrid&&) noexcept = default; + auto operator=(const BaseTwoDimensionalGrid&) -> BaseTwoDimensionalGrid& = default; + auto operator=(BaseTwoDimensionalGrid&&) noexcept -> BaseTwoDimensionalGrid& = default; + virtual ~BaseTwoDimensionalGrid() = default; + + [[nodiscard]] virtual auto GetCellForReading(TIndex x, TIndex y) const -> const TCell& = 0; + [[nodiscard]] virtual auto GetCellForWriting(TIndex x, TIndex y) -> TCell& = 0; + +protected: + TIndex _width {}; + TIndex _height {}; +}; + +template +class DynamicTwoDimensionalGrid : public BaseTwoDimensionalGrid +{ + using base = BaseTwoDimensionalGrid; + +public: + DynamicTwoDimensionalGrid(TIndex width, TIndex height) : + base(width, height) + { + STACK_TRACE_ENTRY(); + } + + [[nodiscard]] auto GetCellForReading(TIndex x, TIndex y) const -> const TCell& override + { + NO_STACK_TRACE_ENTRY(); + + if constexpr (std::is_signed_v) { + RUNTIME_ASSERT(x >= 0); + RUNTIME_ASSERT(y >= 0); + } + + RUNTIME_ASSERT(x < base::_width); + RUNTIME_ASSERT(y < base::_height); + + const auto it = _cells.find(tuple {x, y}); + + if (it == _cells.end()) { + return _emptyCell; + } + else { + return it->second; + } + } + + [[nodiscard]] auto GetCellForWriting(TIndex x, TIndex y) -> TCell& override + { + NO_STACK_TRACE_ENTRY(); + + if constexpr (std::is_signed_v) { + RUNTIME_ASSERT(x >= 0); + RUNTIME_ASSERT(y >= 0); + } + + RUNTIME_ASSERT(x < base::_width); + RUNTIME_ASSERT(y < base::_height); + + const auto it = _cells.find(tuple {x, y}); + + if (it == _cells.end()) { + return _cells.emplace(tuple {x, y}, TCell {}).first->second; + } + else { + return it->second; + } + } + +private: + struct IndexHasher + { + auto operator()(const tuple& index) const noexcept -> size_t; + }; + + unordered_map, TCell, IndexHasher> _cells {}; + const TCell _emptyCell {}; +}; + +template +auto DynamicTwoDimensionalGrid::IndexHasher::operator()(const tuple& index) const noexcept -> size_t +{ + NO_STACK_TRACE_ENTRY(); + + if constexpr (sizeof(TIndex) <= sizeof(size_t) / 2) { + return (static_cast(std::get<0>(index)) << (sizeof(size_t) / 2 * 8)) | static_cast(std::get<1>(index)); + } + else { + return static_cast(std::get<0>(index)) ^ static_cast(std::get<1>(index)); + } +} + +template +class StaticTwoDimensionalGrid : public BaseTwoDimensionalGrid +{ + using base = BaseTwoDimensionalGrid; + +public: + StaticTwoDimensionalGrid(TIndex width, TIndex height) : + base(width, height) + { + STACK_TRACE_ENTRY(); + + _preallocatedCells.resize(static_cast(base::_width) * base::_height); + } + + [[nodiscard]] auto GetCellForReading(TIndex x, TIndex y) const -> const TCell& override + { + NO_STACK_TRACE_ENTRY(); + + if constexpr (std::is_signed_v) { + RUNTIME_ASSERT(x >= 0); + RUNTIME_ASSERT(y >= 0); + } + + RUNTIME_ASSERT(x < base::_width); + RUNTIME_ASSERT(y < base::_height); + + return _preallocatedCells[static_cast(y) * base::_width + x]; + } + + [[nodiscard]] auto GetCellForWriting(TIndex x, TIndex y) -> TCell& override + { + NO_STACK_TRACE_ENTRY(); + + if constexpr (std::is_signed_v) { + RUNTIME_ASSERT(x >= 0); + RUNTIME_ASSERT(y >= 0); + } + + RUNTIME_ASSERT(x < base::_width); + RUNTIME_ASSERT(y < base::_height); + + return _preallocatedCells[static_cast(y) * base::_width + x]; + } + +private: + vector _preallocatedCells {}; + const TCell _emptyCell {}; +}; + template class TwoDimensionalGrid { diff --git a/Source/Server/Map.cpp b/Source/Server/Map.cpp index c5b7202b8d..f6b9155e9e 100644 --- a/Source/Server/Map.cpp +++ b/Source/Server/Map.cpp @@ -57,7 +57,12 @@ Map::Map(FOServer* engine, ident_t id, const ProtoMap* proto, Location* location _width = GetWidth(); _height = GetHeight(); - _hexField.SetSize(_width, _height); + if (engine->Settings.MapInstanceStaticGrid) { + _hexField = std::make_unique>(_width, _height); + } + else { + _hexField = std::make_unique>(_width, _height); + } } Map::~Map() @@ -239,7 +244,7 @@ void Map::AddCritterToField(Critter* cr) const auto hy = cr->GetHexY(); RUNTIME_ASSERT(hx < _width && hy < _height); - auto& field = _hexField.GetCellForWriting(hx, hy); + auto& field = _hexField->GetCellForWriting(hx, hy); RUNTIME_ASSERT(std::find(field.Critters.begin(), field.Critters.end(), cr) == field.Critters.end()); field.Critters.emplace_back(cr); @@ -257,7 +262,7 @@ void Map::RemoveCritterFromField(Critter* cr) const auto hy = cr->GetHexY(); RUNTIME_ASSERT(hx < _width && hy < _height); - auto& field = _hexField.GetCellForWriting(hx, hy); + auto& field = _hexField->GetCellForWriting(hx, hy); const auto it = std::find(field.Critters.begin(), field.Critters.end(), cr); RUNTIME_ASSERT(it != field.Critters.end()); @@ -284,7 +289,7 @@ void Map::SetMultihexCritter(Critter* cr, bool set) const auto ny = static_cast(hy) + sy[i]; if (nx >= 0 && ny >= 0 && nx < _width && ny < _height) { - auto& field = _hexField.GetCellForWriting(static_cast(nx), static_cast(ny)); + auto& field = _hexField->GetCellForWriting(static_cast(nx), static_cast(ny)); if (set) { RUNTIME_ASSERT(std::find(field.MultihexCritters.begin(), field.MultihexCritters.end(), cr) == field.MultihexCritters.end()); @@ -370,7 +375,7 @@ void Map::SetItem(Item* item, uint16 hx, uint16 hy) _items.emplace_back(item); _itemsMap.emplace(item->GetId(), item); - auto& field = _hexField.GetCellForWriting(hx, hy); + auto& field = _hexField->GetCellForWriting(hx, hy); field.Items.emplace_back(item); @@ -382,7 +387,7 @@ void Map::SetItem(Item* item, uint16 hx, uint16 hy) if (item->IsNonEmptyBlockLines()) { GeometryHelper::ForEachBlockLines(item->GetBlockLines(), hx, hy, _width, _height, [this, item](uint16 hx2, uint16 hy2) { - auto& field2 = _hexField.GetCellForWriting(hx2, hy2); + auto& field2 = _hexField->GetCellForWriting(hx2, hy2); field2.BlockLines.emplace_back(item); RecacheHexFlags(field2); }); @@ -411,7 +416,7 @@ void Map::EraseItem(ident_t item_id) const auto hx = item->GetHexX(); const auto hy = item->GetHexY(); - auto& field = _hexField.GetCellForWriting(hx, hy); + auto& field = _hexField->GetCellForWriting(hx, hy); { const auto it = std::find(field.Items.begin(), field.Items.end(), item); @@ -440,7 +445,7 @@ void Map::EraseItem(ident_t item_id) if (item->IsNonEmptyBlockLines()) { GeometryHelper::ForEachBlockLines(item->GetBlockLines(), hx, hy, _width, _height, [this, item](uint16 hx2, uint16 hy2) { - auto& field2 = _hexField.GetCellForWriting(hx2, hy2); + auto& field2 = _hexField->GetCellForWriting(hx2, hy2); const auto it = std::find(field2.BlockLines.begin(), field2.BlockLines.end(), item); RUNTIME_ASSERT(it != field2.BlockLines.end()); field2.BlockLines.erase(it); @@ -490,8 +495,8 @@ auto Map::IsHexMovable(uint16 hx, uint16 hy) const -> bool { NO_STACK_TRACE_ENTRY(); - const auto& field = _hexField.GetCellForReading(hx, hy); - const auto& static_field = _staticMap->HexField.GetCellForReading(hx, hy); + const auto& field = _hexField->GetCellForReading(hx, hy); + const auto& static_field = _staticMap->HexField->GetCellForReading(hx, hy); return !field.IsMoveBlocked && !static_field.IsMoveBlocked; } @@ -500,8 +505,8 @@ auto Map::IsHexShootable(uint16 hx, uint16 hy) const -> bool { NO_STACK_TRACE_ENTRY(); - const auto& field = _hexField.GetCellForReading(hx, hy); - const auto& static_field = _staticMap->HexField.GetCellForReading(hx, hy); + const auto& field = _hexField->GetCellForReading(hx, hy); + const auto& static_field = _staticMap->HexField->GetCellForReading(hx, hy); return !field.IsShootBlocked && !static_field.IsShootBlocked; } @@ -637,7 +642,7 @@ auto Map::IsBlockItem(uint16 hx, uint16 hy) const -> bool { NO_STACK_TRACE_ENTRY(); - const auto& field = _hexField.GetCellForReading(hx, hy); + const auto& field = _hexField->GetCellForReading(hx, hy); return field.IsNoMoveItem; } @@ -646,7 +651,7 @@ auto Map::IsItemTrigger(uint16 hx, uint16 hy) const -> bool { NO_STACK_TRACE_ENTRY(); - const auto& field = _hexField.GetCellForReading(hx, hy); + const auto& field = _hexField->GetCellForReading(hx, hy); return field.IsTriggerItem; } @@ -655,7 +660,7 @@ auto Map::IsItemGag(uint16 hx, uint16 hy) const -> bool { NO_STACK_TRACE_ENTRY(); - const auto& field = _hexField.GetCellForReading(hx, hy); + const auto& field = _hexField->GetCellForReading(hx, hy); return field.IsGagItem; } @@ -674,7 +679,7 @@ auto Map::GetItemHex(uint16 hx, uint16 hy, hstring item_pid, Critter* picker) -> NON_CONST_METHOD_HINT(); - const auto& field = _hexField.GetCellForReading(hx, hy); + const auto& field = _hexField->GetCellForReading(hx, hy); for (auto* item : field.Items) { if ((!item_pid || item->GetProtoId() == item_pid) && (picker == nullptr || (!item->GetIsHidden() && picker->CountIdVisItem(item->GetId())))) { @@ -691,7 +696,7 @@ auto Map::GetItemGag(uint16 hx, uint16 hy) -> Item* NON_CONST_METHOD_HINT(); - const auto& field = _hexField.GetCellForReading(hx, hy); + const auto& field = _hexField->GetCellForReading(hx, hy); for (auto* item : field.Items) { if (item->GetIsGag()) { @@ -717,7 +722,7 @@ auto Map::GetItems(uint16 hx, uint16 hy) -> const vector& NON_CONST_METHOD_HINT(); - const auto& field = _hexField.GetCellForReading(hx, hy); + const auto& field = _hexField->GetCellForReading(hx, hy); return field.Items; } @@ -763,7 +768,7 @@ auto Map::GetItemsTrigger(uint16 hx, uint16 hy) -> vector NON_CONST_METHOD_HINT(); - const auto& field = _hexField.GetCellForReading(hx, hy); + const auto& field = _hexField->GetCellForReading(hx, hy); vector triggers; triggers.reserve(field.Items.size()); @@ -796,7 +801,7 @@ void Map::RecacheHexFlags(uint16 hx, uint16 hy) RUNTIME_ASSERT(hx < _width); RUNTIME_ASSERT(hy < _height); - auto& field = _hexField.GetCellForWriting(hx, hy); + auto& field = _hexField->GetCellForWriting(hx, hy); RecacheHexFlags(field); } @@ -886,7 +891,7 @@ void Map::SetHexManualBlock(uint16 hx, uint16 hy, bool enable, bool full) { STACK_TRACE_ENTRY(); - auto& field = _hexField.GetCellForWriting(hx, hy); + auto& field = _hexField->GetCellForWriting(hx, hy); field.ManualBlock = enable; field.ManualBlockFull = full; @@ -898,7 +903,7 @@ auto Map::IsAnyCritter(uint16 hx, uint16 hy) const -> bool { NO_STACK_TRACE_ENTRY(); - const auto& field = _hexField.GetCellForReading(hx, hy); + const auto& field = _hexField->GetCellForReading(hx, hy); return field.IsNonDeadCritter || field.IsDeadCritter; } @@ -907,7 +912,7 @@ auto Map::IsNonDeadCritter(uint16 hx, uint16 hy) const -> bool { NO_STACK_TRACE_ENTRY(); - const auto& field = _hexField.GetCellForReading(hx, hy); + const auto& field = _hexField->GetCellForReading(hx, hy); return field.IsNonDeadCritter; } @@ -916,7 +921,7 @@ auto Map::IsDeadCritter(uint16 hx, uint16 hy) const -> bool { NO_STACK_TRACE_ENTRY(); - const auto& field = _hexField.GetCellForReading(hx, hy); + const auto& field = _hexField->GetCellForReading(hx, hy); return field.IsDeadCritter; } @@ -927,7 +932,7 @@ auto Map::IsCritter(uint16 hx, uint16 hy, const Critter* cr) const -> bool RUNTIME_ASSERT(cr); - const auto& field = _hexField.GetCellForReading(hx, hy); + const auto& field = _hexField->GetCellForReading(hx, hy); if (field.IsNonDeadCritter || field.IsDeadCritter) { const auto it1 = std::find(field.Critters.begin(), field.Critters.end(), cr); @@ -963,7 +968,7 @@ auto Map::GetNonDeadCritter(uint16 hx, uint16 hy) -> Critter* NON_CONST_METHOD_HINT(); - const auto& field = _hexField.GetCellForReading(hx, hy); + const auto& field = _hexField->GetCellForReading(hx, hy); if (field.IsNonDeadCritter) { for (auto* cr : field.Critters) { @@ -988,7 +993,7 @@ auto Map::GetDeadCritter(uint16 hx, uint16 hy) -> Critter* NON_CONST_METHOD_HINT(); - const auto& field = _hexField.GetCellForReading(hx, hy); + const auto& field = _hexField->GetCellForReading(hx, hy); if (field.IsDeadCritter) { for (auto* cr : field.Critters) { @@ -1152,7 +1157,7 @@ auto Map::IsStaticItemTrigger(uint16 hx, uint16 hy) const -> bool { NO_STACK_TRACE_ENTRY(); - const auto& static_field = _staticMap->HexField.GetCellForReading(hx, hy); + const auto& static_field = _staticMap->HexField->GetCellForReading(hx, hy); return !static_field.TriggerItems.empty(); } @@ -1176,7 +1181,7 @@ auto Map::GetStaticItem(uint16 hx, uint16 hy, hstring pid) -> StaticItem* NON_CONST_METHOD_HINT(); - const auto& static_field = _staticMap->HexField.GetCellForReading(hx, hy); + const auto& static_field = _staticMap->HexField->GetCellForReading(hx, hy); for (auto* item : static_field.StaticItems) { if (!pid || item->GetProtoId() == pid) { @@ -1193,7 +1198,7 @@ auto Map::GetStaticItemsHex(uint16 hx, uint16 hy) -> vector NON_CONST_METHOD_HINT(); - const auto& static_field = _staticMap->HexField.GetCellForReading(hx, hy); + const auto& static_field = _staticMap->HexField->GetCellForReading(hx, hy); return static_field.StaticItems; } @@ -1238,7 +1243,7 @@ auto Map::GetStaticItemsTrigger(uint16 hx, uint16 hy) -> vector NON_CONST_METHOD_HINT(); - const auto& static_field = _staticMap->HexField.GetCellForReading(hx, hy); + const auto& static_field = _staticMap->HexField->GetCellForReading(hx, hy); return static_field.TriggerItems; } diff --git a/Source/Server/Map.h b/Source/Server/Map.h index 42552ba9b1..ad1c9aed5f 100644 --- a/Source/Server/Map.h +++ b/Source/Server/Map.h @@ -59,7 +59,7 @@ struct StaticMap vector TriggerItems {}; }; - TwoDimensionalGrid HexField {}; + unique_ptr> HexField {}; vector> CritterBillets {}; vector> ItemBillets {}; vector> HexItemBillets {}; @@ -181,7 +181,7 @@ class Map final : public ServerEntity, public EntityWithProto, public MapPropert const StaticMap* _staticMap {}; uint16 _width {}; uint16 _height {}; - TwoDimensionalGrid _hexField {}; + unique_ptr> _hexField {}; vector _critters {}; unordered_map _crittersMap {}; vector _playerCritters {}; diff --git a/Source/Server/MapManager.cpp b/Source/Server/MapManager.cpp index 25987cbffa..b0de0ffa55 100644 --- a/Source/Server/MapManager.cpp +++ b/Source/Server/MapManager.cpp @@ -85,7 +85,12 @@ void MapManager::LoadFromResources() const auto map_width = pmap->GetWidth(); const auto map_height = pmap->GetHeight(); - static_map->HexField.SetSize(map_width, map_height); + if (_engine->Settings.ProtoMapStaticGrid) { + static_map->HexField = std::make_unique>(map_width, map_height); + } + else { + static_map->HexField = std::make_unique>(map_width, map_height); + } // Read hashes { @@ -202,10 +207,10 @@ void MapManager::LoadFromResources() if (!item->GetIsHiddenInStatic()) { static_map->StaticItems.emplace_back(item); static_map->StaticItemsById.emplace(item->GetId(), item); - static_map->HexField.GetCellForWriting(hx, hy).StaticItems.emplace_back(item); + static_map->HexField->GetCellForWriting(hx, hy).StaticItems.emplace_back(item); } if (item->GetIsTrigger() || item->GetIsTrap()) { - static_map->HexField.GetCellForWriting(hx, hy).TriggerItems.emplace_back(item); + static_map->HexField->GetCellForWriting(hx, hy).TriggerItems.emplace_back(item); } } else { @@ -233,12 +238,12 @@ void MapManager::LoadFromResources() const auto hy = item->GetHexY(); if (!item->GetIsNoBlock()) { - auto& static_field = static_map->HexField.GetCellForWriting(hx, hy); + auto& static_field = static_map->HexField->GetCellForWriting(hx, hy); static_field.IsMoveBlocked = true; } if (!item->GetIsShootThru()) { - auto& static_field = static_map->HexField.GetCellForWriting(hx, hy); + auto& static_field = static_map->HexField->GetCellForWriting(hx, hy); static_field.IsShootBlocked = true; static_field.IsMoveBlocked = true; } @@ -249,7 +254,7 @@ void MapManager::LoadFromResources() auto hx2 = hx; auto hy2 = hy; if (GeometryHelper::MoveHexByDir(hx2, hy2, k, map_width, map_height)) { - auto& static_field = static_map->HexField.GetCellForWriting(hx2, hy2); + auto& static_field = static_map->HexField->GetCellForWriting(hx2, hy2); static_field.IsMoveBlocked = true; } } @@ -258,7 +263,7 @@ void MapManager::LoadFromResources() if (item->IsNonEmptyBlockLines()) { const auto shooted = item->GetIsShootThru(); GeometryHelper::ForEachBlockLines(item->GetBlockLines(), hx, hy, map_width, map_height, [&static_map, shooted](uint16 hx2, uint16 hy2) { - auto& static_field2 = static_map->HexField.GetCellForWriting(hx2, hy2); + auto& static_field2 = static_map->HexField->GetCellForWriting(hx2, hy2); static_field2.IsMoveBlocked = true; if (!shooted) { static_field2.IsShootBlocked = true; From 4331ca793b3600f1c4c8f8f8d224820dc818e022 Mon Sep 17 00:00:00 2001 From: cvet Date: Tue, 18 Jun 2024 10:29:12 +0300 Subject: [PATCH 12/12] Fixed static items keeping --- Source/Server/MapManager.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/Server/MapManager.cpp b/Source/Server/MapManager.cpp index b0de0ffa55..f43c597584 100644 --- a/Source/Server/MapManager.cpp +++ b/Source/Server/MapManager.cpp @@ -206,7 +206,7 @@ void MapManager::LoadFromResources() if (!item->GetIsHiddenInStatic()) { static_map->StaticItems.emplace_back(item); - static_map->StaticItemsById.emplace(item->GetId(), item); + static_map->StaticItemsById.emplace(item_id, item); static_map->HexField->GetCellForWriting(hx, hy).StaticItems.emplace_back(item); } if (item->GetIsTrigger() || item->GetIsTrap()) {