From 178f21631793d74365c0e777d2063b4fbabbde8d Mon Sep 17 00:00:00 2001 From: elsid Date: Thu, 5 Jun 2025 23:58:41 +0200 Subject: [PATCH 1/2] Add Lua test for passing a NaN value --- scripts/data/integration_tests/test_lua_api/global.lua | 7 +++++++ scripts/data/integration_tests/test_lua_api/menu.lua | 1 + 2 files changed, 8 insertions(+) diff --git a/scripts/data/integration_tests/test_lua_api/global.lua b/scripts/data/integration_tests/test_lua_api/global.lua index 225660b858..31d1b040db 100644 --- a/scripts/data/integration_tests/test_lua_api/global.lua +++ b/scripts/data/integration_tests/test_lua_api/global.lua @@ -344,6 +344,13 @@ testing.registerGlobalTest('load while teleporting - teleport', function() landracer:teleport(player.cell, player.position) end) +testing.registerGlobalTest('nan', function() + local nan = 0.0 / 0.0 + local ok, err = pcall(function() world.setGameTimeScale(nan) end) + testing.expectEqual(ok, false) + testing.expectEqual(err, 'Value must be a finite number') +end) + return { engineHandlers = { onUpdate = testing.updateGlobal, diff --git a/scripts/data/integration_tests/test_lua_api/menu.lua b/scripts/data/integration_tests/test_lua_api/menu.lua index 8c6895a5d8..4f8dbd99c6 100644 --- a/scripts/data/integration_tests/test_lua_api/menu.lua +++ b/scripts/data/integration_tests/test_lua_api/menu.lua @@ -72,6 +72,7 @@ registerGlobalTest('memory limit') registerGlobalTest('vfs') registerGlobalTest('commit crime') registerGlobalTest('record model property') +registerGlobalTest('nan', 'world.setGameTimeScale should not accept nan') registerGlobalTest('player yaw rotation', 'rotating player with controls.yawChange should change rotation') registerGlobalTest('player pitch rotation', 'rotating player with controls.pitchChange should change rotation') From 267ce1ec9bb484fd1e4eabb56658e886b621d55a Mon Sep 17 00:00:00 2001 From: elsid Date: Thu, 5 Jun 2025 23:49:30 +0200 Subject: [PATCH 2/2] Reduce code duplication for finite number --- apps/openmw/mwlua/animationbindings.cpp | 2 +- apps/openmw/mwlua/camerabindings.cpp | 2 +- apps/openmw/mwlua/worldbindings.cpp | 2 +- components/misc/finitenumbers.hpp | 59 ++++++++----------------- 4 files changed, 22 insertions(+), 43 deletions(-) diff --git a/apps/openmw/mwlua/animationbindings.cpp b/apps/openmw/mwlua/animationbindings.cpp index 2f6f60ea3e..ee096a5a35 100644 --- a/apps/openmw/mwlua/animationbindings.cpp +++ b/apps/openmw/mwlua/animationbindings.cpp @@ -100,7 +100,7 @@ namespace MWLua sol::table initAnimationPackage(const Context& context) { - using FiniteFloat = Misc::FiniteFloat; + using Misc::FiniteFloat; auto view = context.sol(); auto mechanics = MWBase::Environment::get().getMechanicsManager(); diff --git a/apps/openmw/mwlua/camerabindings.cpp b/apps/openmw/mwlua/camerabindings.cpp index 345ca9af65..c6461209c5 100644 --- a/apps/openmw/mwlua/camerabindings.cpp +++ b/apps/openmw/mwlua/camerabindings.cpp @@ -16,7 +16,7 @@ namespace MWLua sol::table initCameraPackage(sol::state_view lua) { - using FiniteFloat = Misc::FiniteFloat; + using Misc::FiniteFloat; MWRender::Camera* camera = MWBase::Environment::get().getWorld()->getCamera(); MWRender::RenderingManager* renderingManager = MWBase::Environment::get().getWorld()->getRenderingManager(); diff --git a/apps/openmw/mwlua/worldbindings.cpp b/apps/openmw/mwlua/worldbindings.cpp index c960c4e9e4..c02bad3bd3 100644 --- a/apps/openmw/mwlua/worldbindings.cpp +++ b/apps/openmw/mwlua/worldbindings.cpp @@ -57,7 +57,7 @@ namespace MWLua static void addWorldTimeBindings(sol::table& api, const Context& context) { - using FiniteFloat = Misc::FiniteFloat; + using Misc::FiniteFloat; MWWorld::DateTimeManager* timeManager = MWBase::Environment::get().getWorld()->getTimeManager(); diff --git a/components/misc/finitenumbers.hpp b/components/misc/finitenumbers.hpp index 7d27987c5f..1670791349 100644 --- a/components/misc/finitenumbers.hpp +++ b/components/misc/finitenumbers.hpp @@ -5,69 +5,48 @@ #include #include +#include namespace Misc { - struct FiniteDouble + template + struct FiniteNumber { - double mValue; - FiniteDouble(double v) + T mValue; + + FiniteNumber(T v) { if (!std::isfinite(v)) throw std::invalid_argument("Value must be a finite number"); mValue = v; } - operator double() const { return mValue; } + + operator T() const { return mValue; } }; - struct FiniteFloat - { - float mValue; - FiniteFloat(float v) - { - if (!std::isfinite(v)) - throw std::invalid_argument("Value must be a finite number"); - mValue = v; - } - operator float() const { return mValue; } - }; + using FiniteDouble = FiniteNumber; + + using FiniteFloat = FiniteNumber; } namespace sol { - using FiniteDouble = Misc::FiniteDouble; - using FiniteFloat = Misc::FiniteFloat; - - template + template bool sol_lua_check( - sol::types, lua_State* L, int index, Handler&& handler, sol::stack::record& tracking) + types>, lua_State* state, int index, Handler&& handler, stack::record& tracking) { - bool success = sol::stack::check(L, lua_absindex(L, index), handler); + bool success = stack::check(state, lua_absindex(state, index), std::forward(handler)); tracking.use(1); return success; } - static FiniteDouble sol_lua_get(sol::types, lua_State* L, int index, sol::stack::record& tracking) + template + static Misc::FiniteNumber sol_lua_get( + types>, lua_State* state, int index, stack::record& tracking) { - double val = sol::stack::get(L, lua_absindex(L, index)); + T value = stack::get(state, lua_absindex(state, index)); tracking.use(1); - return FiniteDouble(val); - } - - template - bool sol_lua_check( - sol::types, lua_State* L, int index, Handler&& handler, sol::stack::record& tracking) - { - bool success = sol::stack::check(L, lua_absindex(L, index), handler); - tracking.use(1); - return success; - } - - static FiniteFloat sol_lua_get(sol::types, lua_State* L, int index, sol::stack::record& tracking) - { - float val = sol::stack::get(L, lua_absindex(L, index)); - tracking.use(1); - return FiniteFloat(val); + return value; } }