From 9c2cb5f4ec2eafa5b4b633090d9bcf8e901d5b7a Mon Sep 17 00:00:00 2001 From: Robert Burnham Date: Fri, 10 Jul 2026 17:13:20 -0500 Subject: [PATCH 1/4] Fix unbindaction not clearing scancode bindings --- rts/Game/UI/KeyBindings.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/rts/Game/UI/KeyBindings.cpp b/rts/Game/UI/KeyBindings.cpp index 9bafd6ca54..4dd9e09711 100644 --- a/rts/Game/UI/KeyBindings.cpp +++ b/rts/Game/UI/KeyBindings.cpp @@ -740,7 +740,13 @@ bool CKeyBindings::UnBindAction(const std::string& command) RECOIL_DETAILED_TRACY_ZONE; if (debugEnabled) LOG("[CKeyBindings::%s] command=%s", __func__, command.c_str()); - return RemoveActionFromKeyMap(command, codeBindings) || RemoveActionFromKeyMap(command, scanBindings); + + // clear both maps; || would short-circuit and leave the scancode binding when + // the action is also bound to a keycode + const bool removedFromCode = RemoveActionFromKeyMap(command, codeBindings); + const bool removedFromScan = RemoveActionFromKeyMap(command, scanBindings); + + return removedFromCode || removedFromScan; } From 6c9781525213cbe39b4af8e0ed5b059e2e420f81 Mon Sep 17 00:00:00 2001 From: Bruno Da Silva Date: Mon, 13 Jul 2026 21:38:15 +0000 Subject: [PATCH 2/4] fix: bump pr-downloader to suppress false positive gcc warning --- tools/pr-downloader | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/pr-downloader b/tools/pr-downloader index 1b95b70bdb..09a1f37c77 160000 --- a/tools/pr-downloader +++ b/tools/pr-downloader @@ -1 +1 @@ -Subproject commit 1b95b70bdb63923f21f2b6b08240dd769cc733b9 +Subproject commit 09a1f37c77a014f24c3116ac7b7d2e318d0ce0de From 3b76f9778aba9f0ef8baa3f71851406d28ec0107 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Ptaszek?= Date: Tue, 14 Jul 2026 00:37:16 +0200 Subject: [PATCH 3/4] `Spring.SetSkyBoxTexture` performs setup if needed Previously a map had to have a skybox texture right from the start for it to be usable. Now sets it up at runtime. --- rts/Lua/LuaUnsyncedCtrl.cpp | 3 +-- rts/Rendering/Env/ISky.cpp | 24 ++++++++++++++++++++++++ rts/Rendering/Env/ISky.h | 1 + 3 files changed, 26 insertions(+), 2 deletions(-) diff --git a/rts/Lua/LuaUnsyncedCtrl.cpp b/rts/Lua/LuaUnsyncedCtrl.cpp index 8156e83f52..2079d9724c 100644 --- a/rts/Lua/LuaUnsyncedCtrl.cpp +++ b/rts/Lua/LuaUnsyncedCtrl.cpp @@ -2150,8 +2150,7 @@ int LuaUnsyncedCtrl::SetSkyBoxTexture(lua_State* L) if (CLuaHandle::GetHandleSynced(L)) return 0; - if (const auto& sky = ISky::GetSky(); sky != nullptr) - sky->SetLuaTexture(ParseLuaTextureData(L, false)); + ISky::SetSkyLuaTexture(ParseLuaTextureData(L, false)); return 0; } diff --git a/rts/Rendering/Env/ISky.cpp b/rts/Rendering/Env/ISky.cpp index 1e44ecabeb..b662d8293e 100644 --- a/rts/Rendering/Env/ISky.cpp +++ b/rts/Rendering/Env/ISky.cpp @@ -89,6 +89,30 @@ void ISky::SetSky() } } +void ISky::SetSkyLuaTexture(const MapTextureData& td) +{ + if (sky == nullptr) + return; + + /* TODO: consider if perhaps there should be some way to set the + * sky to one of the other classes (CModernSky, etc) via Lua. */ + + if (td.id != 0u && dynamic_cast(sky.get()) == nullptr) { + auto luaSky = std::make_unique(td.id, td.size.x, td.size.y); + + if (luaSky->IsValid()) { + sky = std::move(luaSky); + return; + } + + LOG_L(L_WARNING, "[ISky::%s] failed to create SkyBox from Lua texture (%u), keeping current sky", __func__, td.id); + return; + } + + /* FIXME: td.id == 0 reaches here. Untested in recent times */ + sky->SetLuaTexture(td); +} + void ISky::SetSkyAxisAngle(const float4& skyAxisAngleRaw) { auto axis = float3{ skyAxisAngleRaw.x, skyAxisAngleRaw.y, skyAxisAngleRaw.z }; diff --git a/rts/Rendering/Env/ISky.h b/rts/Rendering/Env/ISky.h index e0632e96d5..62fc19d188 100644 --- a/rts/Rendering/Env/ISky.h +++ b/rts/Rendering/Env/ISky.h @@ -50,6 +50,7 @@ class ISky void SetUpdated() { updated = true; } public: static void SetSky(); + static void SetSkyLuaTexture(const MapTextureData& td); static auto& GetSky() { return sky; } static void KillSky() { sky = nullptr; } public: From d306d399f9636aaf7ad516cc1979d7558ad98d81 Mon Sep 17 00:00:00 2001 From: Tom J Nowell Date: Sat, 4 Jul 2026 23:55:05 +0100 Subject: [PATCH 4/4] LuaParser: run Spring.TimeCheck's callback under unitsync/dedicated Under UNITSYNC and DEDICATED, TimeCheck compiled to `return 0`, silently dropping the function it was handed. The shipped gamedata/defs.lua wraps all unitdef/weapondef/etc. loading in Spring.TimeCheck(...), so ProcessUnits() ends up with an empty root and throws "root unitdef table invalid" - unitsync reports zero units for every game whose defs.lua uses TimeCheck (the standard springcontent path). Only the profiling timer needs to be excluded from those builds, not the call itself. --- rts/Lua/LuaParser.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/rts/Lua/LuaParser.cpp b/rts/Lua/LuaParser.cpp index 45c44ebf9e..6ca8394fc4 100644 --- a/rts/Lua/LuaParser.cpp +++ b/rts/Lua/LuaParser.cpp @@ -501,12 +501,13 @@ void LuaParser::AddString(int key, const std::string& value) int LuaParser::TimeCheck(lua_State* L) { - #if (!defined(UNITSYNC) && !defined(DEDICATED)) if (!lua_isstring(L, 1) || !lua_isfunction(L, 2)) luaL_error(L, "Invalid arguments to TimeCheck('string', func, ...)"); { + #if (!defined(UNITSYNC) && !defined(DEDICATED)) ScopedOnceTimer timer(lua_tostring(L, 1)); + #endif lua_remove(L, 1); @@ -519,9 +520,6 @@ int LuaParser::TimeCheck(lua_State* L) } return lua_gettop(L); - #else - return 0; - #endif }