From 1f11c97e64cc64d9960e0bc8776a6fb4b5762875 Mon Sep 17 00:00:00 2001 From: sprunk Date: Sat, 7 Dec 2024 03:07:11 +0100 Subject: [PATCH 01/12] `Spring.AllocateTable` -> `table.new` Some Lua extensions (notably, LuaJIT) seem to offer this feature as `table.new`, with the same args we do, and it does feel like a more natural place for it to be. --- rts/Lua/CMakeLists.txt | 1 + rts/Lua/LuaHandle.cpp | 5 +++++ rts/Lua/LuaTableExtra.cpp | 43 +++++++++++++++++++++++++++++++++++++ rts/Lua/LuaTableExtra.h | 9 ++++++++ rts/Lua/LuaUnsyncedCtrl.cpp | 26 ---------------------- rts/Lua/LuaUnsyncedCtrl.h | 1 - 6 files changed, 58 insertions(+), 27 deletions(-) create mode 100644 rts/Lua/LuaTableExtra.cpp create mode 100644 rts/Lua/LuaTableExtra.h diff --git a/rts/Lua/CMakeLists.txt b/rts/Lua/CMakeLists.txt index fc6e6f9102..5e6eb62be5 100644 --- a/rts/Lua/CMakeLists.txt +++ b/rts/Lua/CMakeLists.txt @@ -41,6 +41,7 @@ set(sources_engine_Lua "${CMAKE_CURRENT_SOURCE_DIR}/LuaSyncedMoveCtrl.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/LuaSyncedRead.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/LuaSyncedTable.cpp" + "${CMAKE_CURRENT_SOURCE_DIR}/LuaTableExtra.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/LuaTextures.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/LuaAtlasTextures.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/LuaUI.cpp" diff --git a/rts/Lua/LuaHandle.cpp b/rts/Lua/LuaHandle.cpp index 3dac9b6ac2..1925f142d0 100644 --- a/rts/Lua/LuaHandle.cpp +++ b/rts/Lua/LuaHandle.cpp @@ -12,6 +12,7 @@ #include "LuaOpenGL.h" #include "LuaBitOps.h" #include "LuaMathExtra.h" +#include "LuaTableExtra.h" #include "LuaUtils.h" #include "LuaZip.h" #include "Game/Game.h" @@ -3847,6 +3848,10 @@ bool CLuaHandle::AddBasicCalls(lua_State* L) LuaMathExtra::PushEntries(L); lua_pop(L, 1); + lua_getglobal(L, "table"); + LuaTableExtra::PushEntries(L); + lua_pop(L, 1); + return true; } diff --git a/rts/Lua/LuaTableExtra.cpp b/rts/Lua/LuaTableExtra.cpp new file mode 100644 index 0000000000..c29cea6fb9 --- /dev/null +++ b/rts/Lua/LuaTableExtra.cpp @@ -0,0 +1,43 @@ +/* This file is part of the Spring engine (GPL v2 or later), see LICENSE.html */ + +#include "LuaTableExtra.h" +#include "LuaUtils.h" + +/****************************************************************************** + * table extensions + * @module TableExtra + * @see rts/Lua/LuaTableExtra.cpp +******************************************************************************/ + +/*** Returns a table with preallocated memory + * + * Returns an empty table with more memory allocated. + * This lets you microoptimize cases where a table receives + * a lot of elements and you know the number beforehand, + * such as one for each UnitDef, by avoiding reallocation. + * + * @function table.new + * @number nArray hint for count of array elements + * @number nHashed hint for count of hashtable elements + * @treturn table + */ +static int TableExtra_new(lua_State* L) +{ + int nArray = luaL_optinteger(L, 1, 0); + int nHash = luaL_optinteger(L, 2, 0); + + if (nArray < 0) + nArray = 0; + if (nHash < 0) + nHash = 0; + + lua_createtable(L, nArray, nHash); + + return 1; +} + +bool LuaTableExtra::PushEntries(lua_State* L) +{ + LuaPushNamedCFunc(L, "new", TableExtra_new); + return true; +} diff --git a/rts/Lua/LuaTableExtra.h b/rts/Lua/LuaTableExtra.h new file mode 100644 index 0000000000..ee0d9432dd --- /dev/null +++ b/rts/Lua/LuaTableExtra.h @@ -0,0 +1,9 @@ +/* This file is part of the Recoil engine (GPL v2 or later), see LICENSE.html */ + +#pragma once + +struct lua_State; + +namespace LuaTableExtra { + bool PushEntries(lua_State* L); +}; diff --git a/rts/Lua/LuaUnsyncedCtrl.cpp b/rts/Lua/LuaUnsyncedCtrl.cpp index b777056b0e..ecd00e26a5 100644 --- a/rts/Lua/LuaUnsyncedCtrl.cpp +++ b/rts/Lua/LuaUnsyncedCtrl.cpp @@ -240,7 +240,6 @@ bool LuaUnsyncedCtrl::PushEntries(lua_State* L) REGISTER_LUA_CFUNC(SetConfigString); REGISTER_LUA_CFUNC(CreateDir); - REGISTER_LUA_CFUNC(AllocateTable); REGISTER_LUA_CFUNC(SendCommands); REGISTER_LUA_CFUNC(GiveOrder); @@ -2624,31 +2623,6 @@ int LuaUnsyncedCtrl::CreateDir(lua_State* L) return 1; } -/*** - * - * @function Spring.AllocateTable - * @number narr hint for count of array elements - * @number nrec hint for count of record elements - * @treturn table - */ -int LuaUnsyncedCtrl::AllocateTable(lua_State* L) -{ - int narr = luaL_optinteger(L, 1, 0); - int nrec = luaL_optinteger(L, 2, 0); - - if (narr < 0) { - narr = 0; - } - if (nrec < 0) { - nrec = 0; - } - - lua_createtable(L, narr, nrec); - - return 1; -} - - /****************************************************************************** * GUI diff --git a/rts/Lua/LuaUnsyncedCtrl.h b/rts/Lua/LuaUnsyncedCtrl.h index 5a420df329..13829bc566 100644 --- a/rts/Lua/LuaUnsyncedCtrl.h +++ b/rts/Lua/LuaUnsyncedCtrl.h @@ -117,7 +117,6 @@ class LuaUnsyncedCtrl { static int SetConfigString(lua_State* L); static int CreateDir(lua_State* L); - static int AllocateTable(lua_State* L); static int Reload(lua_State* L); static int Restart(lua_State* L); From 02df97ef8a0dc9a0ccb87ca657faed877a708446 Mon Sep 17 00:00:00 2001 From: loveridge Date: Sat, 7 Dec 2024 11:22:23 -0700 Subject: [PATCH 02/12] allow skipping the factory move command insertion (#1539) --- doc/changelog.txt | 1 + rts/Sim/Misc/ModInfo.cpp | 2 ++ rts/Sim/Misc/ModInfo.h | 2 ++ rts/Sim/Units/UnitTypes/Factory.cpp | 9 ++++++--- 4 files changed, 11 insertions(+), 3 deletions(-) diff --git a/doc/changelog.txt b/doc/changelog.txt index 871ec7a03a..053a066ecf 100644 --- a/doc/changelog.txt +++ b/doc/changelog.txt @@ -159,6 +159,7 @@ Misc: - Fix when a client that takes too long to connect can potentially trigger a desync. https://github.com/beyond-all-reason/spring/issues/1406 - Prevent logging general log information before the game engine has started. https://github.com/beyond-all-reason/spring/issues/683 + - New modinfo setting to skip issuing newly created units a move command off of the factory pad: insertBuiltUnitMoveCommand. Sim: - Improved performance of long-range path finding requests (TKPFS) diff --git a/rts/Sim/Misc/ModInfo.cpp b/rts/Sim/Misc/ModInfo.cpp index 7e3cc448ae..08aade523c 100644 --- a/rts/Sim/Misc/ModInfo.cpp +++ b/rts/Sim/Misc/ModInfo.cpp @@ -44,6 +44,7 @@ void CModInfo::ResetState() constructionDecay = true; constructionDecayTime = int(6.66 * GAME_SPEED); constructionDecaySpeed = 0.03f; + insertBuiltUnitMoveCommand = true; } { debrisDamage = 50.0f; @@ -213,6 +214,7 @@ void CModInfo::Init(const std::string& modFileName) constructionDecay = constructionTbl.GetBool("constructionDecay", constructionDecay); constructionDecayTime = (int)(constructionTbl.GetFloat("constructionDecayTime", (float)constructionDecayTime / GAME_SPEED) * GAME_SPEED); constructionDecaySpeed = std::max(constructionTbl.GetFloat("constructionDecaySpeed", constructionDecaySpeed), 0.01f); + insertBuiltUnitMoveCommand = constructionTbl.GetBool("insertBuiltUnitMoveCommand", insertBuiltUnitMoveCommand); } { diff --git a/rts/Sim/Misc/ModInfo.h b/rts/Sim/Misc/ModInfo.h index ec2b493602..825c8d223a 100644 --- a/rts/Sim/Misc/ModInfo.h +++ b/rts/Sim/Misc/ModInfo.h @@ -69,6 +69,8 @@ class CModInfo int constructionDecayTime; /// How fast do they decay? float constructionDecaySpeed; + /// When units are created, issue a move command off of the factory pad. + bool insertBuiltUnitMoveCommand; // Damage behaviour /// unit pieces flying off (usually on death) diff --git a/rts/Sim/Units/UnitTypes/Factory.cpp b/rts/Sim/Units/UnitTypes/Factory.cpp index 0c6eeef0a8..f5012fc967 100644 --- a/rts/Sim/Units/UnitTypes/Factory.cpp +++ b/rts/Sim/Units/UnitTypes/Factory.cpp @@ -7,6 +7,7 @@ #include "Map/Ground.h" #include "Map/ReadMap.h" #include "Sim/Misc/GroundBlockingObjectMap.h" +#include "Sim/Misc/ModInfo.h" #include "Sim/Misc/QuadField.h" #include "Sim/Misc/TeamHandler.h" #include "Sim/MoveTypes/MoveType.h" @@ -443,7 +444,7 @@ void CFactory::AssignBuildeeOrders(CUnit* unit) { Command c(CMD_MOVE); - if (!unit->unitDef->canfly) { + if (!unit->unitDef->canfly && modInfo.insertBuiltUnitMoveCommand) { // HACK: when a factory has a rallypoint set far enough away // to trigger the non-admissable path estimators, we want to // avoid units getting stuck inside by issuing them an extra @@ -472,7 +473,9 @@ void CFactory::AssignBuildeeOrders(CUnit* unit) { } if (unitCmdQue.empty()) { - unitCAI->GiveCommand(c); + if (modInfo.insertBuiltUnitMoveCommand) { + unitCAI->GiveCommand(c); + } // copy factory orders for new unit for (auto ci = factoryCmdQue.begin(); ci != factoryCmdQue.end(); ++ci) { @@ -494,7 +497,7 @@ void CFactory::AssignBuildeeOrders(CUnit* unit) { unitCAI->GiveCommand(c); } - } else { + } else if (modInfo.insertBuiltUnitMoveCommand) { unitCmdQue.push_front(c); } } From f83afe11f908472ed64f05a6f0b0f5aaaee28a9c Mon Sep 17 00:00:00 2001 From: LHoG <1476261+lhog@users.noreply.github.com> Date: Sun, 8 Dec 2024 22:31:08 +0100 Subject: [PATCH 03/12] Report "Waiting for game to start" for local games/demos/loads --- rts/Game/PreGame.cpp | 11 ++++++++--- rts/Menu/SelectMenu.cpp | 1 - 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/rts/Game/PreGame.cpp b/rts/Game/PreGame.cpp index 02e5c61d48..0ae97f11da 100644 --- a/rts/Game/PreGame.cpp +++ b/rts/Game/PreGame.cpp @@ -191,10 +191,15 @@ bool CPreGame::Draw() font->SetTextColor(color.x, color.y, color.z, color.w); if (!clientNet->Connected()) { - if (clientSetup->isHost) - font->glFormat(0.5f, 0.60f, 2.0f, FONT_CENTER | FONT_SCALE | FONT_NORM, "Waiting for server to start"); - else + if (clientSetup->isHost) { + if (clientSetup->hostIP == "localhost") + font->glFormat(0.5f, 0.60f, 2.0f, FONT_CENTER | FONT_SCALE | FONT_NORM, "Waiting for game to start"); + else + font->glFormat(0.5f, 0.60f, 2.0f, FONT_CENTER | FONT_SCALE | FONT_NORM, "Waiting for server to start"); + } + else { font->glFormat(0.5f, 0.60f, 2.0f, FONT_CENTER | FONT_SCALE | FONT_NORM, "Connecting to server (%ds)", (spring_gettime() - connectTimer).toSecsi()); + } } else { font->glPrint(0.5f, 0.60f, 2.0f, FONT_CENTER | FONT_SCALE | FONT_NORM, "Waiting for server response"); } diff --git a/rts/Menu/SelectMenu.cpp b/rts/Menu/SelectMenu.cpp index d4012fb2af..0d5d85cab4 100644 --- a/rts/Menu/SelectMenu.cpp +++ b/rts/Menu/SelectMenu.cpp @@ -259,7 +259,6 @@ void SelectMenu::Single() selw->userScript.clear(); pregame = new CPreGame(clientSetup); - auto f = &CPreGame::LoadSetupScript; pregame->AsyncExecute(&CPreGame::LoadSetupScript, StartScriptGen::CreateDefaultSetup(selw->userMap, selw->userMod, selw->userScript, clientSetup->myPlayerName)); //pregame->LoadSetupScript(StartScriptGen::CreateDefaultSetup(selw->userMap, selw->userMod, selw->userScript, clientSetup->myPlayerName)); return (agui::gui->RmElement(this)); From 05c5724c3178571cb3bcdcc7d910dd6b13d6af21 Mon Sep 17 00:00:00 2001 From: saurtron Date: Wed, 11 Dec 2024 15:14:30 +0100 Subject: [PATCH 04/12] Fontconfig windows workaround v2 (#1809) * Custom xml for windows since mingw builds won't work with the fontconfig special strings. --------- Co-authored-by: sprunk --- rts/Rendering/Fonts/CFontTexture.cpp | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/rts/Rendering/Fonts/CFontTexture.cpp b/rts/Rendering/Fonts/CFontTexture.cpp index b969389c18..33f7cbce7d 100644 --- a/rts/Rendering/Fonts/CFontTexture.cpp +++ b/rts/Rendering/Fonts/CFontTexture.cpp @@ -150,15 +150,20 @@ class FtLibraryHandler { // and system fonts included. also linux actually has system config files that can be used by fontconfig. #ifdef _WIN32 - // fontconfig will resolve the special keys here. - static constexpr const char* configFmt = R"(WINDOWSFONTDIRfontcacheLOCAL_APPDATA_FONTCONFIG_CACHE)"; + static constexpr auto winFontPath = "%WINDIR%\\fonts"; + const int neededSize = ExpandEnvironmentStrings(winFontPath, nullptr, 0); + std::vector osFontsDir (neededSize); + ExpandEnvironmentStrings(winFontPath, osFontsDir.data(), osFontsDir.size()); + + static constexpr const char* configFmt = R"(%sfontcache)"; + const std::string configFmtVar = fmt::sprintf(configFmt, osFontsDir.data()); #else - static constexpr const char* configFmt = R"(fontcache)"; + const std::string configFmtVar = R"(fontcache)"; #endif #ifdef _WIN32 // Explicitly set the config with xml for windows. - res = FcConfigParseAndLoadFromMemory(config, reinterpret_cast(configFmt), FcTrue); + res = FcConfigParseAndLoadFromMemory(config, reinterpret_cast(configFmtVar.c_str()), FcTrue); #else // Load system configuration (passing 0 here so fc will use the default os config file if possible). res = FcConfigParseAndLoad(config, 0, true); @@ -166,7 +171,7 @@ class FtLibraryHandler { if (res) { #ifndef _WIN32 // add local cache after system config for linux - FcConfigParseAndLoadFromMemory(config, reinterpret_cast(configFmt), FcTrue); + FcConfigParseAndLoadFromMemory(config, reinterpret_cast(configFmtVar.c_str()), FcTrue); #endif LOG_MSG("[%s] Using Fontconfig light init", false, __func__); @@ -191,7 +196,7 @@ class FtLibraryHandler { config = fcConfig; // add our cache at the back of the new config. - FcConfigParseAndLoadFromMemory(config, reinterpret_cast(configFmt), FcTrue); + FcConfigParseAndLoadFromMemory(config, reinterpret_cast(configFmtVar.c_str()), FcTrue); } else { LOG_MSG("%s config and fonts. No system fallbacks will be available", false, errprefix.c_str()); } From e41b7150348f6240745d1ac72e51439e30569be4 Mon Sep 17 00:00:00 2001 From: LHoG <1476261+lhog@users.noreply.github.com> Date: Mon, 16 Dec 2024 02:02:04 +0100 Subject: [PATCH 05/12] This file has been on my disk far too long, time to commit it, though it's not used anywhere(yet) --- rts/System/creg/STL_Bitset.h | 51 ++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 rts/System/creg/STL_Bitset.h diff --git a/rts/System/creg/STL_Bitset.h b/rts/System/creg/STL_Bitset.h new file mode 100644 index 0000000000..390e6abb81 --- /dev/null +++ b/rts/System/creg/STL_Bitset.h @@ -0,0 +1,51 @@ +#pragma once + +#include "creg_cond.h" +#include +#include +#include +#include +#include "../TemplateUtils.hpp" + +#ifdef USING_CREG + +namespace creg +{ + template + class BitsetType : public IType + { + public: + using T = std::bitset; + BitsetType() : IType(sizeof(T)) { } + ~BitsetType() { } + + void Serialize(ISerializer* s, void* instance) + { + T& ct = *(T*)instance; + + std::array bytesRep = {0}; + + if (s->IsWriting()) + bytesRep = std::bit_cast(ct); + + for (auto& b : bytesRep) { + s->SerializeInt(b, sizeof(b)); + } + + if (!s->IsWriting()) + ct = std::bit_cast(bytesRep); + } + std::string GetName() const { + return std::string("bitset<" + std::to_string(N) + ">"); + } + }; + + template + struct DeduceType > { + static std::unique_ptr Get() { + return std::unique_ptr(new BitsetType()); + } + }; +} + +#endif // USING_CREG \ No newline at end of file From eae2809daba963d6682fdbc1f91cd117ef9cf60a Mon Sep 17 00:00:00 2001 From: Saurtron Date: Mon, 16 Dec 2024 05:52:05 +0100 Subject: [PATCH 06/12] Add Spring.SetUnitIconDraw --- rts/Lua/LuaUnsyncedCtrl.cpp | 24 +++++++++++++++++++++++- rts/Lua/LuaUnsyncedCtrl.h | 1 + 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/rts/Lua/LuaUnsyncedCtrl.cpp b/rts/Lua/LuaUnsyncedCtrl.cpp index ecd00e26a5..04ccfc41da 100644 --- a/rts/Lua/LuaUnsyncedCtrl.cpp +++ b/rts/Lua/LuaUnsyncedCtrl.cpp @@ -227,7 +227,9 @@ bool LuaUnsyncedCtrl::PushEntries(lua_State* L) REGISTER_LUA_CFUNC(AddUnitIcon); REGISTER_LUA_CFUNC(FreeUnitIcon); - REGISTER_LUA_CFUNC(UnitIconSetDraw); + REGISTER_LUA_CFUNC(UnitIconSetDraw); // deprecated + REGISTER_LUA_CFUNC(SetUnitIconDraw); + REGISTER_LUA_CFUNC(ExtractModArchiveFile); @@ -2425,11 +2427,31 @@ int LuaUnsyncedCtrl::FreeUnitIcon(lua_State* L) /*** * * @function Spring.UnitIconSetDraw + * Deprecated: use Spring.SetUnitIconDraw instead. + * @see Spring.SetUnitIconDraw * @number unitID * @bool drawIcon * @treturn nil */ int LuaUnsyncedCtrl::UnitIconSetDraw(lua_State* L) +{ + static bool deprecatedMsgDone = false; + if (!deprecatedMsgDone) { + LOG_L(L_WARNING, "Spring.UnitIconSetDraw is deprecated. Please use Spring.SetUnitIconDraw instead."); + deprecatedMsgDone = true; + } + return LuaUnsyncedCtrl::SetUnitIconDraw(L); +} + + +/*** + * + * @function Spring.SetUnitIconDraw + * @number unitID + * @bool drawIcon + * @treturn nil + */ +int LuaUnsyncedCtrl::SetUnitIconDraw(lua_State* L) { CUnit* unit = ParseCtrlUnit(L, __func__, 1); diff --git a/rts/Lua/LuaUnsyncedCtrl.h b/rts/Lua/LuaUnsyncedCtrl.h index 13829bc566..3358942d34 100644 --- a/rts/Lua/LuaUnsyncedCtrl.h +++ b/rts/Lua/LuaUnsyncedCtrl.h @@ -103,6 +103,7 @@ class LuaUnsyncedCtrl { static int AddUnitIcon(lua_State* L); static int FreeUnitIcon(lua_State* L); + static int SetUnitIconDraw(lua_State* L); static int UnitIconSetDraw(lua_State* L); static int ExtractModArchiveFile(lua_State* L); From 63b8152e5db17f3c0e6d2eca245a843ea2d0d994 Mon Sep 17 00:00:00 2001 From: saurtron Date: Mon, 16 Dec 2024 15:17:39 +0100 Subject: [PATCH 07/12] Allow negative index at GetUnitCurrentCommand to index from queue end. (#1813) * Allow negative index at GetUnitCurrentCommand to index from the end of the queue. * Make forward compat possible --------- Co-authored-by: sprunk --- rts/Lua/LuaConstEngine.cpp | 3 ++- rts/Lua/LuaSyncedRead.cpp | 15 ++++++++++++--- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/rts/Lua/LuaConstEngine.cpp b/rts/Lua/LuaConstEngine.cpp index 7fcace04d1..f0a47d5937 100644 --- a/rts/Lua/LuaConstEngine.cpp +++ b/rts/Lua/LuaConstEngine.cpp @@ -39,7 +39,8 @@ bool LuaConstEngine::PushEntries(lua_State* L) lua_pushliteral(L, "FeatureSupport"); - lua_createtable(L, 0, 2); + lua_createtable(L, 0, 3); + LuaPushNamedBool(L, "NegativeGetUnitCurrentCommand", true); LuaPushNamedBool(L, "hasExitOnlyYardmaps", true); LuaPushNamedNumber(L, "rmlUiApiVersion", 1); lua_rawset(L, -3); diff --git a/rts/Lua/LuaSyncedRead.cpp b/rts/Lua/LuaSyncedRead.cpp index d6164188d6..a6bed0597d 100644 --- a/rts/Lua/LuaSyncedRead.cpp +++ b/rts/Lua/LuaSyncedRead.cpp @@ -5977,6 +5977,10 @@ static void PackCommandQueue(lua_State* L, const CCommandQueue& commands, size_t /*** * * @function Spring.GetUnitCurrentCommand + * + * @number unitID Unit id. + * @number cmdIndex Command index to get. If negative will count from the end of the queue, + * for example -1 will be the last command. */ int LuaSyncedRead::GetUnitCurrentCommand(lua_State* L) { @@ -5989,10 +5993,15 @@ int LuaSyncedRead::GetUnitCurrentCommand(lua_State* L) const CFactoryCAI* factoryCAI = dynamic_cast(commandAI); const CCommandQueue* queue = (factoryCAI == nullptr)? &commandAI->commandQue : &factoryCAI->newUnitCommands; - // - 1 to convert from lua index to C index - const unsigned int cmdIndex = luaL_optint(L, 2, 1) - 1; + int cmdIndex = luaL_optint(L, 2, 1); + if (cmdIndex > 0) { + // - 1 to convert from lua index to C index + cmdIndex -= 1; + } else { + cmdIndex = queue->size()-cmdIndex; + } - if (cmdIndex >= queue->size()) + if (cmdIndex >= queue->size() || cmdIndex < 0) return 0; const Command& cmd = queue->at(cmdIndex); From e4d0e47d45f5f7ef2f77e042621f57588c35b127 Mon Sep 17 00:00:00 2001 From: lostsquirrel1 Date: Mon, 16 Dec 2024 18:15:55 +0000 Subject: [PATCH 08/12] Stablize sorts used by path finders (#1805) * applied std:tie treat to priority queue for QTPFS * add comment to avoid future confusion. --- rts/Sim/Path/HAPFS/PathDataTypes.h | 8 ++++++-- rts/Sim/Path/QTPFS/PathThreads.h | 19 +++++++++++-------- 2 files changed, 17 insertions(+), 10 deletions(-) diff --git a/rts/Sim/Path/HAPFS/PathDataTypes.h b/rts/Sim/Path/HAPFS/PathDataTypes.h index b108106aa7..cf83b119c6 100644 --- a/rts/Sim/Path/HAPFS/PathDataTypes.h +++ b/rts/Sim/Path/HAPFS/PathDataTypes.h @@ -37,9 +37,13 @@ struct PathNode { /// functor to define node priority +/// This needs to guarantee that the sorting is stable. struct lessCost { - inline bool operator() (const PathNode* x, const PathNode* y) const { - return (x->fCost == y->fCost) ? (x->gCost < y->gCost) : (x->fCost > y->fCost); + inline bool operator() (const PathNode* lhs, const PathNode* rhs) const { + // fCost == gCost + hCost. + // When fCosts are the same, prioritize the node closest the goal. Since we don't have hCost to hand, we know + // that hCost == fCost - gCost. This is why we invert the left/right side for the gCost comparison. + return std::tie(lhs->fCost, rhs->gCost, lhs->nodeNum) > std::tie(rhs->fCost, lhs->gCost, rhs->nodeNum); } }; diff --git a/rts/Sim/Path/QTPFS/PathThreads.h b/rts/Sim/Path/QTPFS/PathThreads.h index 62b4bdc212..9c6be8b543 100644 --- a/rts/Sim/Path/QTPFS/PathThreads.h +++ b/rts/Sim/Path/QTPFS/PathThreads.h @@ -90,12 +90,6 @@ namespace QTPFS { }; struct SearchQueueNode { - bool operator < (const SearchQueueNode& n) const { return (heapPriority < n.heapPriority); } - bool operator > (const SearchQueueNode& n) const { return (heapPriority > n.heapPriority); } - bool operator == (const SearchQueueNode& n) const { return (heapPriority == n.heapPriority); } - bool operator <= (const SearchQueueNode& n) const { return (heapPriority <= n.heapPriority); } - bool operator >= (const SearchQueueNode& n) const { return (heapPriority >= n.heapPriority); } - SearchQueueNode(int index, float newPriorty) : heapPriority(newPriorty) , nodeIndex(index) @@ -105,9 +99,18 @@ namespace QTPFS { int nodeIndex; }; + /// Functor to define node priority. + /// Needs to guarantee stable ordering, even if the sorting algorithm itself is not stable. + struct ShouldMoveTowardsBottomOfPriorityQueue { + inline bool operator() (const SearchQueueNode& lhs, const SearchQueueNode& rhs) const { + return std::tie(lhs.heapPriority, lhs.nodeIndex) > std::tie(rhs.heapPriority, rhs.nodeIndex); + } + }; + + // Reminder that std::priority does comparisons to push element back to the bottom. So using - // std::greater here means the smallest value will be top() - typedef std::priority_queue, std::greater> SearchPriorityQueue; + // ShouldMoveTowardsBottomOfPriorityQueue here means the smallest value will be top() + typedef std::priority_queue, ShouldMoveTowardsBottomOfPriorityQueue> SearchPriorityQueue; struct SearchThreadData { From 21ce6c9f4e23d6f0347fbf62b22a4a91dd7c7195 Mon Sep 17 00:00:00 2001 From: Saurtron Date: Mon, 9 Dec 2024 09:33:19 +0100 Subject: [PATCH 09/12] Don't preload glyphs for non-alphanumeric fonts. --- rts/Rendering/Fonts/CFontTexture.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/rts/Rendering/Fonts/CFontTexture.cpp b/rts/Rendering/Fonts/CFontTexture.cpp index 33f7cbce7d..6476f97a7c 100644 --- a/rts/Rendering/Fonts/CFontTexture.cpp +++ b/rts/Rendering/Fonts/CFontTexture.cpp @@ -606,6 +606,9 @@ CFontTexture::CFontTexture(const std::string& fontfile, int size, int _outlinesi // precache ASCII glyphs & kernings (save them in kerningPrecached array for better lvl2 cpu cache hitrate) //preload Glyphs + // if given face doesn't contain alphanumerics, don't preload it + if (!FT_Get_Char_Index(face, 'a')) + return; LoadWantedGlyphs(32, 127); for (char32_t i = 32; i < 127; ++i) { const auto& lgl = GetGlyph(i); From b983f3457cc55ad278a0cdb6c08c04362a2cf6ec Mon Sep 17 00:00:00 2001 From: saurtron Date: Mon, 16 Dec 2024 19:20:13 +0100 Subject: [PATCH 10/12] Apply radar error to lua spatial queries. (#1811) * Apply radar error to lua spatial queries. * Factor out some calls CLuaHandle::GetHandleReadAllyTeam(L) since those can use the already defined readAllyTeam. --------- Co-authored-by: sprunk --- rts/Lua/LuaSyncedRead.cpp | 157 +++++++++++++++++++++++++------------- 1 file changed, 105 insertions(+), 52 deletions(-) diff --git a/rts/Lua/LuaSyncedRead.cpp b/rts/Lua/LuaSyncedRead.cpp index a6bed0597d..a0fcb78d5c 100644 --- a/rts/Lua/LuaSyncedRead.cpp +++ b/rts/Lua/LuaSyncedRead.cpp @@ -2908,6 +2908,8 @@ int LuaSyncedRead::GetTeamUnitCount(lua_State* L) // unit // readTeam for MY_UNIT_TEST // allegiance for SIMPLE_TEAM_TEST and VISIBLE_TEAM_TEST +// readAllyTeam for ALLY_UNIT_TEST and ENEMY_UNIT_TEST +// readAllyTeam, fullRead for UNIT_ERROR_POS #define NULL_TEST ; // always passes @@ -2925,12 +2927,32 @@ int LuaSyncedRead::GetTeamUnitCount(lua_State* L) if (unit->team != readTeam) { continue; } #define ALLY_UNIT_TEST \ - if (unit->allyteam != CLuaHandle::GetHandleReadAllyTeam(L)) { continue; } + if (unit->allyteam != readAllyTeam) { continue; } #define ENEMY_UNIT_TEST \ - if (unit->allyteam == CLuaHandle::GetHandleReadAllyTeam(L)) { continue; } \ + if (unit->allyteam == readAllyTeam) { continue; } \ if (!LuaUtils::IsUnitVisible(L, unit)) { continue; } +#define UNIT_POS \ + const float3& p = unit->midPos; + +#define UNIT_ERROR_POS \ + float3 p = unit->midPos; \ + if (!LuaUtils::IsAllyUnit(L, unit)) \ + p += unit->GetLuaErrorVector(readAllyTeam, fullRead); + + +/* Apply team error to planar mins/maxs boxes */ +void ApplyPlanarTeamError(lua_State* L, int allegiance, float3& mins, float3& maxs) { + if ((allegiance >= 0 && !LuaUtils::IsAlliedTeam(L, allegiance)) || + !(allegiance == LuaUtils::MyUnits || allegiance == LuaUtils::AllyUnits)) { + const int readAllyTeam = CLuaHandle::GetHandleReadAllyTeam(L); + const float allyTeamError = losHandler->GetAllyTeamRadarErrorSize(readAllyTeam); + const float3 allyTeamError3(allyTeamError, 0.0f, allyTeamError); + mins -= allyTeamError3; + maxs += allyTeamError3; + } +} /*** * @@ -2949,12 +2971,25 @@ int LuaSyncedRead::GetUnitsInRectangle(lua_State* L) const float xmax = luaL_checkfloat(L, 3); const float zmax = luaL_checkfloat(L, 4); - const float3 mins(xmin, 0.0f, zmin); - const float3 maxs(xmax, 0.0f, zmax); + float3 mins(xmin, 0.0f, zmin); + float3 maxs(xmax, 0.0f, zmax); const int allegiance = LuaUtils::ParseAllegiance(L, __func__, 5); + const int readAllyTeam = CLuaHandle::GetHandleReadAllyTeam(L); + const bool fullRead = CLuaHandle::GetHandleFullRead(L); -#define RECTANGLE_TEST ; // no test, GetUnitsExact is sufficient +#define RECTANGLE_TEST \ + const float x = p.x; \ + const float z = p.z; \ + if ((x < xmin) || (x > xmax)) { \ + continue; \ + } \ + if ((z < zmin) || (z > zmax)) { \ + continue; \ + } + + if (!fullRead) + ApplyPlanarTeamError(L, allegiance, mins, maxs); QuadFieldQuery qfQuery; quadField.GetUnitsExact(qfQuery, mins, maxs); @@ -2962,23 +2997,23 @@ int LuaSyncedRead::GetUnitsInRectangle(lua_State* L) if (allegiance >= 0) { if (LuaUtils::IsAlliedTeam(L, allegiance)) { - LOOP_UNIT_CONTAINER(SIMPLE_TEAM_TEST, RECTANGLE_TEST, true); + LOOP_UNIT_CONTAINER(SIMPLE_TEAM_TEST, NULL_TEST, true); } else { - LOOP_UNIT_CONTAINER(VISIBLE_TEAM_TEST, RECTANGLE_TEST, true); + LOOP_UNIT_CONTAINER(VISIBLE_TEAM_TEST, UNIT_ERROR_POS RECTANGLE_TEST, true); } } else if (allegiance == LuaUtils::MyUnits) { const int readTeam = CLuaHandle::GetHandleReadTeam(L); - LOOP_UNIT_CONTAINER(MY_UNIT_TEST, RECTANGLE_TEST, true); + LOOP_UNIT_CONTAINER(MY_UNIT_TEST, NULL_TEST, true); } else if (allegiance == LuaUtils::AllyUnits) { - LOOP_UNIT_CONTAINER(ALLY_UNIT_TEST, RECTANGLE_TEST, true); + LOOP_UNIT_CONTAINER(ALLY_UNIT_TEST, NULL_TEST, true); } else if (allegiance == LuaUtils::EnemyUnits) { - LOOP_UNIT_CONTAINER(ENEMY_UNIT_TEST, RECTANGLE_TEST, true); + LOOP_UNIT_CONTAINER(ENEMY_UNIT_TEST, UNIT_ERROR_POS RECTANGLE_TEST, true); } else { // AllUnits - LOOP_UNIT_CONTAINER(VISIBLE_TEST, RECTANGLE_TEST, true); + LOOP_UNIT_CONTAINER(VISIBLE_TEST, UNIT_ERROR_POS RECTANGLE_TEST, true); } return 1; @@ -3006,40 +3041,49 @@ int LuaSyncedRead::GetUnitsInBox(lua_State* L) const float ymax = luaL_checkfloat(L, 5); const float zmax = luaL_checkfloat(L, 6); - const float3 mins(xmin, 0.0f, zmin); - const float3 maxs(xmax, 0.0f, zmax); + float3 mins(xmin, 0.0f, zmin); + float3 maxs(xmax, 0.0f, zmax); const int allegiance = LuaUtils::ParseAllegiance(L, __func__, 7); + const int readAllyTeam = CLuaHandle::GetHandleReadAllyTeam(L); + const bool fullRead = CLuaHandle::GetHandleFullRead(L); #define BOX_TEST \ - const float y = unit->midPos.y; \ + const float y = p.y; \ if ((y < ymin) || (y > ymax)) { \ - continue; \ + continue; \ } +#define BOX_TEST_FULL \ + BOX_TEST \ + RECTANGLE_TEST + + if (!fullRead) + ApplyPlanarTeamError(L, allegiance, mins, maxs); + QuadFieldQuery qfQuery; quadField.GetUnitsExact(qfQuery, mins, maxs); const auto& units = (*qfQuery.units); if (allegiance >= 0) { if (LuaUtils::IsAlliedTeam(L, allegiance)) { - LOOP_UNIT_CONTAINER(SIMPLE_TEAM_TEST, BOX_TEST, true); + LOOP_UNIT_CONTAINER(SIMPLE_TEAM_TEST, UNIT_POS BOX_TEST, true); } else { - LOOP_UNIT_CONTAINER(VISIBLE_TEAM_TEST, BOX_TEST, true); + LOOP_UNIT_CONTAINER(VISIBLE_TEAM_TEST, UNIT_ERROR_POS BOX_TEST_FULL, true); } } else if (allegiance == LuaUtils::MyUnits) { const int readTeam = CLuaHandle::GetHandleReadTeam(L); - LOOP_UNIT_CONTAINER(MY_UNIT_TEST, BOX_TEST, true); + LOOP_UNIT_CONTAINER(MY_UNIT_TEST, UNIT_POS BOX_TEST, true); } else if (allegiance == LuaUtils::AllyUnits) { - LOOP_UNIT_CONTAINER(ALLY_UNIT_TEST, BOX_TEST, true); + LOOP_UNIT_CONTAINER(ALLY_UNIT_TEST, UNIT_POS BOX_TEST, true); } else if (allegiance == LuaUtils::EnemyUnits) { - LOOP_UNIT_CONTAINER(ENEMY_UNIT_TEST, BOX_TEST, true); + LOOP_UNIT_CONTAINER(ENEMY_UNIT_TEST, UNIT_ERROR_POS BOX_TEST_FULL, true); } else { // AllUnits - LOOP_UNIT_CONTAINER(VISIBLE_TEST, BOX_TEST, true); + LOOP_UNIT_CONTAINER(VISIBLE_TEST, UNIT_ERROR_POS BOX_TEST_FULL, true); } return 1; @@ -3061,13 +3105,14 @@ int LuaSyncedRead::GetUnitsInCylinder(lua_State* L) const float radius = luaL_checkfloat(L, 3); const float radSqr = (radius * radius); - const float3 mins(x - radius, 0.0f, z - radius); - const float3 maxs(x + radius, 0.0f, z + radius); + float3 mins(x - radius, 0.0f, z - radius); + float3 maxs(x + radius, 0.0f, z + radius); const int allegiance = LuaUtils::ParseAllegiance(L, __func__, 4); + const int readAllyTeam = CLuaHandle::GetHandleReadAllyTeam(L); + const bool fullRead = CLuaHandle::GetHandleFullRead(L); #define CYLINDER_TEST \ - const float3& p = unit->midPos; \ const float dx = (p.x - x); \ const float dz = (p.z - z); \ const float dist = ((dx * dx) + (dz * dz)); \ @@ -3075,29 +3120,32 @@ int LuaSyncedRead::GetUnitsInCylinder(lua_State* L) continue; \ } \ + if (!fullRead) + ApplyPlanarTeamError(L, allegiance, mins, maxs); + QuadFieldQuery qfQuery; quadField.GetUnitsExact(qfQuery, mins, maxs); const auto& units = (*qfQuery.units); if (allegiance >= 0) { if (LuaUtils::IsAlliedTeam(L, allegiance)) { - LOOP_UNIT_CONTAINER(SIMPLE_TEAM_TEST, CYLINDER_TEST, true); + LOOP_UNIT_CONTAINER(SIMPLE_TEAM_TEST, UNIT_POS CYLINDER_TEST, true); } else { - LOOP_UNIT_CONTAINER(VISIBLE_TEAM_TEST, CYLINDER_TEST, true); + LOOP_UNIT_CONTAINER(VISIBLE_TEAM_TEST, UNIT_ERROR_POS CYLINDER_TEST, true); } } else if (allegiance == LuaUtils::MyUnits) { const int readTeam = CLuaHandle::GetHandleReadTeam(L); - LOOP_UNIT_CONTAINER(MY_UNIT_TEST, CYLINDER_TEST, true); + LOOP_UNIT_CONTAINER(MY_UNIT_TEST, UNIT_POS CYLINDER_TEST, true); } else if (allegiance == LuaUtils::AllyUnits) { - LOOP_UNIT_CONTAINER(ALLY_UNIT_TEST, CYLINDER_TEST, true); + LOOP_UNIT_CONTAINER(ALLY_UNIT_TEST, UNIT_POS CYLINDER_TEST, true); } else if (allegiance == LuaUtils::EnemyUnits) { - LOOP_UNIT_CONTAINER(ENEMY_UNIT_TEST, CYLINDER_TEST, true); + LOOP_UNIT_CONTAINER(ENEMY_UNIT_TEST, UNIT_ERROR_POS CYLINDER_TEST, true); } else { // AllUnits - LOOP_UNIT_CONTAINER(VISIBLE_TEST, CYLINDER_TEST, true); + LOOP_UNIT_CONTAINER(VISIBLE_TEST, UNIT_ERROR_POS CYLINDER_TEST, true); } return 1; @@ -3122,13 +3170,14 @@ int LuaSyncedRead::GetUnitsInSphere(lua_State* L) const float radSqr = (radius * radius); const float3 pos(x, y, z); - const float3 mins(x - radius, 0.0f, z - radius); - const float3 maxs(x + radius, 0.0f, z + radius); + float3 mins(x - radius, 0.0f, z - radius); + float3 maxs(x + radius, 0.0f, z + radius); const int allegiance = LuaUtils::ParseAllegiance(L, __func__, 5); + const int readAllyTeam = CLuaHandle::GetHandleReadAllyTeam(L); + const bool fullRead = CLuaHandle::GetHandleFullRead(L); #define SPHERE_TEST \ - const float3& p = unit->midPos; \ const float dx = (p.x - x); \ const float dy = (p.y - y); \ const float dz = (p.z - z); \ @@ -3138,29 +3187,32 @@ int LuaSyncedRead::GetUnitsInSphere(lua_State* L) continue; \ } \ + if (!fullRead) + ApplyPlanarTeamError(L, allegiance, mins, maxs); + QuadFieldQuery qfQuery; quadField.GetUnitsExact(qfQuery, mins, maxs); const auto& units = (*qfQuery.units); if (allegiance >= 0) { if (LuaUtils::IsAlliedTeam(L, allegiance)) { - LOOP_UNIT_CONTAINER(SIMPLE_TEAM_TEST, SPHERE_TEST, true); + LOOP_UNIT_CONTAINER(SIMPLE_TEAM_TEST, UNIT_POS SPHERE_TEST, true); } else { - LOOP_UNIT_CONTAINER(VISIBLE_TEAM_TEST, SPHERE_TEST, true); + LOOP_UNIT_CONTAINER(VISIBLE_TEAM_TEST, UNIT_ERROR_POS SPHERE_TEST, true); } } else if (allegiance == LuaUtils::MyUnits) { const int readTeam = CLuaHandle::GetHandleReadTeam(L); - LOOP_UNIT_CONTAINER(MY_UNIT_TEST, SPHERE_TEST, true); + LOOP_UNIT_CONTAINER(MY_UNIT_TEST, UNIT_POS SPHERE_TEST, true); } else if (allegiance == LuaUtils::AllyUnits) { - LOOP_UNIT_CONTAINER(ALLY_UNIT_TEST, SPHERE_TEST, true); + LOOP_UNIT_CONTAINER(ALLY_UNIT_TEST, UNIT_POS SPHERE_TEST, true); } else if (allegiance == LuaUtils::EnemyUnits) { - LOOP_UNIT_CONTAINER(ENEMY_UNIT_TEST, SPHERE_TEST, true); + LOOP_UNIT_CONTAINER(ENEMY_UNIT_TEST, UNIT_ERROR_POS SPHERE_TEST, true); } else { // AllUnits - LOOP_UNIT_CONTAINER(VISIBLE_TEST, SPHERE_TEST, true); + LOOP_UNIT_CONTAINER(VISIBLE_TEST, UNIT_ERROR_POS SPHERE_TEST, true); } return 1; @@ -3172,12 +3224,11 @@ struct Plane { }; -static inline bool UnitInPlanes(const CUnit* unit, const vector& planes) +static inline bool UnitInPlanes(const float3& pos, const float radius, const vector& planes) { - const float3& pos = unit->midPos; for (const Plane& p: planes) { const float dist = (pos.x * p.x) + (pos.y * p.y) + (pos.z * p.z) + p.d; - if ((dist - unit->radius) > 0.0f) { + if ((dist - radius) > 0.0f) { return false; // outside } } @@ -3245,11 +3296,13 @@ int LuaSyncedRead::GetUnitsInPlanes(lua_State* L) } #define PLANES_TEST \ - if (!UnitInPlanes(unit, planes)) { \ + if (!UnitInPlanes(p, unit->radius, planes)) { \ continue; \ } const int readTeam = CLuaHandle::GetHandleReadTeam(L); + const int readAllyTeam = CLuaHandle::GetHandleReadAllyTeam(L); + const bool fullRead = CLuaHandle::GetHandleFullRead(L); lua_newtable(L); @@ -3259,32 +3312,32 @@ int LuaSyncedRead::GetUnitsInPlanes(lua_State* L) if (allegiance >= 0) { if (allegiance == team) { if (LuaUtils::IsAlliedTeam(L, allegiance)) { - LOOP_UNIT_CONTAINER(NULL_TEST, PLANES_TEST, false); + LOOP_UNIT_CONTAINER(NULL_TEST, UNIT_POS PLANES_TEST, false); } else { - LOOP_UNIT_CONTAINER(VISIBLE_TEST, PLANES_TEST, false); + LOOP_UNIT_CONTAINER(VISIBLE_TEST, UNIT_ERROR_POS PLANES_TEST, false); } } } else if (allegiance == LuaUtils::MyUnits) { if (readTeam == team) { - LOOP_UNIT_CONTAINER(NULL_TEST, PLANES_TEST, false); + LOOP_UNIT_CONTAINER(NULL_TEST, UNIT_POS PLANES_TEST, false); } } else if (allegiance == LuaUtils::AllyUnits) { - if (CLuaHandle::GetHandleReadAllyTeam(L) == teamHandler.AllyTeam(team)) { - LOOP_UNIT_CONTAINER(NULL_TEST, PLANES_TEST, false); + if (readAllyTeam == teamHandler.AllyTeam(team)) { + LOOP_UNIT_CONTAINER(NULL_TEST, UNIT_POS PLANES_TEST, false); } } else if (allegiance == LuaUtils::EnemyUnits) { - if (CLuaHandle::GetHandleReadAllyTeam(L) != teamHandler.AllyTeam(team)) { - LOOP_UNIT_CONTAINER(VISIBLE_TEST, PLANES_TEST, false); + if (readAllyTeam != teamHandler.AllyTeam(team)) { + LOOP_UNIT_CONTAINER(VISIBLE_TEST, UNIT_ERROR_POS PLANES_TEST, false); } } else { // AllUnits if (LuaUtils::IsAlliedTeam(L, team)) { - LOOP_UNIT_CONTAINER(NULL_TEST, PLANES_TEST, false); + LOOP_UNIT_CONTAINER(NULL_TEST, UNIT_POS PLANES_TEST, false); } else { - LOOP_UNIT_CONTAINER(VISIBLE_TEST, PLANES_TEST, false); + LOOP_UNIT_CONTAINER(VISIBLE_TEST, UNIT_ERROR_POS PLANES_TEST, false); } } } From d7f4de7c80ebdd98dfce942a43060dc8d971aecb Mon Sep 17 00:00:00 2001 From: saurtron Date: Mon, 16 Dec 2024 23:31:23 +0100 Subject: [PATCH 11/12] Add Spring.GetUnitCommandCount for getting a units command queue count (#1814) Also mark `Spring.GetUnitCommands(unitID, 0)` as deprecated (but still return the expected output as before) --- rts/Lua/LuaSyncedRead.cpp | 26 ++++++++++++++++++++++++++ rts/Lua/LuaSyncedRead.h | 1 + 2 files changed, 27 insertions(+) diff --git a/rts/Lua/LuaSyncedRead.cpp b/rts/Lua/LuaSyncedRead.cpp index a0fcb78d5c..bd6ea4548c 100644 --- a/rts/Lua/LuaSyncedRead.cpp +++ b/rts/Lua/LuaSyncedRead.cpp @@ -267,6 +267,7 @@ bool LuaSyncedRead::PushEntries(lua_State* L) REGISTER_LUA_CFUNC(GetUnitBlocking); REGISTER_LUA_CFUNC(GetUnitMoveTypeData); + REGISTER_LUA_CFUNC(GetUnitCommandCount); REGISTER_LUA_CFUNC(GetUnitCommands); REGISTER_LUA_CFUNC(GetUnitCurrentCommand); REGISTER_LUA_CFUNC(GetFactoryCounts); @@ -6123,6 +6124,11 @@ int LuaSyncedRead::GetUnitCommands(lua_State* L) // *get wants the actual commands PackCommandQueue(L, *queue, numCmds); } else { + static bool deprecatedMsgDone = false; + if (!deprecatedMsgDone) { + LOG_L(L_WARNING, "Getting the command count using GetUnitCommands/GetCommandQueue is deprecated. Please use Spring.GetUnitCommandCount instead."); + deprecatedMsgDone = true; + } // *get just wants the queue's size lua_pushnumber(L, queue->size()); } @@ -6166,6 +6172,26 @@ int LuaSyncedRead::GetFactoryCommands(lua_State* L) return 1; } +/*** Get the number of commands in a units queue. + * + * @number unitID + */ +int LuaSyncedRead::GetUnitCommandCount(lua_State* L) +{ + const CUnit* unit = ParseAllyUnit(L, __func__, 1); + + if (unit == nullptr) + return 0; + + const CCommandAI* commandAI = unit->commandAI; + + const CFactoryCAI* factoryCAI = dynamic_cast(commandAI); + const CCommandQueue* queue = (factoryCAI == nullptr)? &commandAI->commandQue : &factoryCAI->newUnitCommands; + + lua_pushnumber(L, queue->size()); + + return 1; +} /*** * diff --git a/rts/Lua/LuaSyncedRead.h b/rts/Lua/LuaSyncedRead.h index e6fae6952a..9b7e27c140 100644 --- a/rts/Lua/LuaSyncedRead.h +++ b/rts/Lua/LuaSyncedRead.h @@ -169,6 +169,7 @@ class LuaSyncedRead { static int GetUnitBlocking(lua_State* L); static int GetUnitMoveTypeData(lua_State* L); + static int GetUnitCommandCount(lua_State* L); static int GetUnitCommands(lua_State* L); static int GetUnitCurrentCommand(lua_State* L); static int GetFactoryCounts(lua_State* L); From 6d3e02f3802ecd29fc77242aaef7e77a3fb2ca10 Mon Sep 17 00:00:00 2001 From: Beherith Date: Mon, 16 Dec 2024 23:35:15 +0100 Subject: [PATCH 12/12] Tracy zones2 Add further once-per-frame zones, colorize top-level zones consistently (#1198) * Tracy: Separate Sim::Projectiles::Update into synced and unsynced zones * Correclty color top-level tracy zones, add some minor once-per-frame zones. * Add Tracy Zones to Minimap drawing, and to ProjectileDrawer --- rts/Game/GameHelper.cpp | 2 +- rts/Game/UI/MiniMap.cpp | 4 ++-- rts/Rendering/Env/Particles/ProjectileDrawer.cpp | 10 ++++++++-- rts/Sim/Projectiles/ProjectileHandler.cpp | 5 ++++- rts/Sim/Units/UnitHandler.cpp | 4 ++-- 5 files changed, 17 insertions(+), 8 deletions(-) diff --git a/rts/Game/GameHelper.cpp b/rts/Game/GameHelper.cpp index 54e1c1d0a3..f8b8b669da 100644 --- a/rts/Game/GameHelper.cpp +++ b/rts/Game/GameHelper.cpp @@ -62,7 +62,7 @@ void CGameHelper::Kill() void CGameHelper::Update() { - RECOIL_DETAILED_TRACY_ZONE; + ZoneScopedC(tracy::Color::Goldenrod); const int wdIdx = gs->frameNum & (waitingDamages.size() - 1); // need to use explicit indexing because CUnit::DoDamage diff --git a/rts/Game/UI/MiniMap.cpp b/rts/Game/UI/MiniMap.cpp index f902413a2d..96200dcd67 100644 --- a/rts/Game/UI/MiniMap.cpp +++ b/rts/Game/UI/MiniMap.cpp @@ -1265,7 +1265,7 @@ void CMiniMap::DrawMinimizedButtonLoop() const void CMiniMap::DrawForReal(bool useNormalizedCoors, bool updateTex, bool luaCall) { - ZoneScopedN("MiniMap::DrawForReal"); + ZoneScopedNC("MiniMap::DrawForReal", tracy::Color::Goldenrod); if (minimized) return; @@ -1915,7 +1915,7 @@ void CMiniMap::DrawUnitRanges() const void CMiniMap::DrawWorldStuff() const { - RECOIL_DETAILED_TRACY_ZONE; + ZoneScoped; glPushMatrix(); if (flipped) { diff --git a/rts/Rendering/Env/Particles/ProjectileDrawer.cpp b/rts/Rendering/Env/Particles/ProjectileDrawer.cpp index 85f6caf5b3..8383011737 100644 --- a/rts/Rendering/Env/Particles/ProjectileDrawer.cpp +++ b/rts/Rendering/Env/Particles/ProjectileDrawer.cpp @@ -654,8 +654,14 @@ void CProjectileDrawer::DrawProjectilesMiniMap() glDisable(GL_PROGRAM_POINT_SIZE); sh.Enable(); - CProjectile::GetMiniMapLinesRB().DrawArrays(GL_LINES); - CProjectile::GetMiniMapPointsRB().DrawArrays(GL_POINTS); + { + ZoneScopedN("DrawProjectilesMiniMap::MiniMapLinesRB"); + CProjectile::GetMiniMapLinesRB().DrawArrays(GL_LINES); + } + { + ZoneScopedN("DrawProjectilesMiniMap::MiniMapPointsRB"); + CProjectile::GetMiniMapPointsRB().DrawArrays(GL_POINTS); + } sh.Disable(); if (pntsz) diff --git a/rts/Sim/Projectiles/ProjectileHandler.cpp b/rts/Sim/Projectiles/ProjectileHandler.cpp index 38b426cc4f..05fdb4571a 100644 --- a/rts/Sim/Projectiles/ProjectileHandler.cpp +++ b/rts/Sim/Projectiles/ProjectileHandler.cpp @@ -191,6 +191,8 @@ void CProjectileHandler::UpdateProjectilesImpl() // WARNING: same as above but for p->Update() if constexpr (synced) { + + SCOPED_TIMER("Sim::Projectiles::UpdateSyncedST"); for (size_t i = 0; i < pc.size(); ++i) { CProjectile* p = pc[i]; assert(p != nullptr); @@ -204,6 +206,7 @@ void CProjectileHandler::UpdateProjectilesImpl() } } else { + SCOPED_TIMER("Sim::Projectiles::UpdateUnsyncedMT"); for_mt_chunk(0, pc.size(), [&pc](int i) { CProjectile* p = pc[i]; assert(p != nullptr); @@ -338,7 +341,7 @@ void CProjectileHandler::Update() // precache part of particles count calculation that else becomes very heavy { - ZoneScopedN("ProjectileHandler::CountParticles"); + ZoneScopedNC("ProjectileHandler::CountParticles", tracy::Color::Goldenrod); frameCurrentParticles = 0; for (const CProjectile* p : projectiles[true]) { diff --git a/rts/Sim/Units/UnitHandler.cpp b/rts/Sim/Units/UnitHandler.cpp index 1f649d1025..8bf40e1bce 100644 --- a/rts/Sim/Units/UnitHandler.cpp +++ b/rts/Sim/Units/UnitHandler.cpp @@ -284,7 +284,7 @@ bool CUnitHandler::QueueDeleteUnit(CUnit* unit) void CUnitHandler::DeleteUnits() { - RECOIL_DETAILED_TRACY_ZONE; + ZoneScopedC(tracy::Color::Goldenrod); while (!unitsToBeRemoved.empty()) { DeleteUnit(unitsToBeRemoved.back()); unitsToBeRemoved.pop_back(); @@ -343,7 +343,7 @@ void CUnitHandler::UpdateUnitMoveTypes() void CUnitHandler::UpdateUnitLosStates() { - ZoneScoped; + ZoneScopedC(tracy::Color::Goldenrod); for (CUnit* unit: activeUnits) { for (int at = 0; at < teamHandler.ActiveAllyTeams(); ++at) { unit->UpdateLosStatus(at);