diff --git a/Shared/mods/deathmatch/logic/lua/CLuaFunctionParser.h b/Shared/mods/deathmatch/logic/lua/CLuaFunctionParser.h index c9408682d61..3b50cc7001b 100644 --- a/Shared/mods/deathmatch/logic/lua/CLuaFunctionParser.h +++ b/Shared/mods/deathmatch/logic/lua/CLuaFunctionParser.h @@ -352,19 +352,41 @@ struct CLuaFunctionParserBase if constexpr (std::is_same_v) return dummy_type{}; // primitive types are directly popped - else if constexpr (std::is_same_v || std::is_same_v || std::is_integral_v) + else if constexpr (std::is_same_v || std::is_same_v) return lua::PopPrimitive(L, index); - // floats/doubles may not be NaN - else if constexpr (std::is_same_v || std::is_same_v) + else if constexpr (std::is_same_v) + return lua::PopPrimitive(L, index); + else if constexpr (std::is_integral_v || std::is_floating_point_v) // bool is an integral type, so must pop it before ^^ { - T value = lua::PopPrimitive(L, index); - if (std::isnan(value)) - { + const auto number = lua::PopPrimitive(L, index); + + const auto SetError = [&](const char* expected, const char* got) { // Subtract one from the index, as the call to lua::PopPrimitive above increments the index, even if the // underlying element is of a wrong type - SetBadArgumentError(L, "number", index - 1, "NaN"); + SetBadArgumentError(L, expected, index - 1, got); + }; + + if (std::isnan(number)) + { + SetError("number", "NaN"); + return static_cast(number); + } + + if (std::isinf(number)) { + SetError("number", "inf"); + return static_cast(number); } - return value; + + // NOTE/TODO: Use C++20 `std::in_range` here instead + // For now this doesn't do all the safety checks, but this should be "good enough" [until we switch to C++20] + if constexpr (std::is_integral_v && std::is_unsigned_v) + { + SetError("positive number", "negative"); + + return static_cast(static_cast(number)); + } + + return static_cast(number); } else if constexpr (std::is_enum_v) { @@ -488,10 +510,7 @@ struct CLuaFunctionParserBase { if (lua_isnumber(L, index)) { - CVector2D vec; - vec.fX = lua::PopPrimitive(L, index); - vec.fY = lua::PopPrimitive(L, index); - return vec; + return { PopUnsafe(L, index), PopUnsafe(L, index) }; } else { @@ -520,11 +539,7 @@ struct CLuaFunctionParserBase { if (lua_isnumber(L, index)) { - CVector vec; - vec.fX = lua::PopPrimitive(L, index); - vec.fY = lua::PopPrimitive(L, index); - vec.fZ = lua::PopPrimitive(L, index); - return vec; + return { PopUnsafe(L, index), PopUnsafe(L, index), PopUnsafe(L, index) }; } else { @@ -551,12 +566,8 @@ struct CLuaFunctionParserBase { if (lua_isnumber(L, index)) { - CVector4D vec; - vec.fX = lua::PopPrimitive(L, index); - vec.fY = lua::PopPrimitive(L, index); - vec.fZ = lua::PopPrimitive(L, index); - vec.fW = lua::PopPrimitive(L, index); - return vec; + return { PopUnsafe(L, index), PopUnsafe(L, index), + PopUnsafe(L, index), PopUnsafe(L, index) }; } else { @@ -583,19 +594,17 @@ struct CLuaFunctionParserBase { if (lua_isnumber(L, index)) { + const auto ReadVector = [&] { + return CVector(PopUnsafe(L, index), PopUnsafe(L, index), PopUnsafe(L, index)); + }; + CMatrix matrix; - matrix.vRight.fX = lua::PopPrimitive(L, index); - matrix.vRight.fY = lua::PopPrimitive(L, index); - matrix.vRight.fZ = lua::PopPrimitive(L, index); - matrix.vFront.fX = lua::PopPrimitive(L, index); - matrix.vFront.fY = lua::PopPrimitive(L, index); - matrix.vFront.fZ = lua::PopPrimitive(L, index); - matrix.vUp.fX = lua::PopPrimitive(L, index); - matrix.vUp.fY = lua::PopPrimitive(L, index); - matrix.vUp.fZ = lua::PopPrimitive(L, index); - matrix.vPos.fX = lua::PopPrimitive(L, index); - matrix.vPos.fY = lua::PopPrimitive(L, index); - matrix.vPos.fZ = lua::PopPrimitive(L, index); + + matrix.vRight = ReadVector(); + matrix.vFront = ReadVector(); + matrix.vUp = ReadVector(); + matrix.vPos = ReadVector(); + return matrix; } else @@ -635,7 +644,7 @@ struct CLuaFunctionParserBase return static_cast(result); } else if constexpr (std::is_same_v) - return static_cast(lua::PopPrimitive(L, index)); + return static_cast(static_cast(lua::PopPrimitive(L, index))); else if constexpr (std::is_same_v) { CLuaArgument argument; diff --git a/Shared/mods/deathmatch/logic/lua/LuaBasic.cpp b/Shared/mods/deathmatch/logic/lua/LuaBasic.cpp index cec6a1bf51d..9dbc467be46 100644 --- a/Shared/mods/deathmatch/logic/lua/LuaBasic.cpp +++ b/Shared/mods/deathmatch/logic/lua/LuaBasic.cpp @@ -29,66 +29,6 @@ namespace lua return outValue; } - template <> - int PopPrimitive(lua_State* L, int& index) - { - return static_cast(lua_tonumber(L, index++)); - } - - template <> - unsigned int PopPrimitive(lua_State* L, int& index) - { - return static_cast(lua_tonumber(L, index++)); - } - - template <> - short PopPrimitive(lua_State* L, int& index) - { - return static_cast(lua_tonumber(L, index++)); - } - - template <> - unsigned short PopPrimitive(lua_State* L, int& index) - { - return static_cast(lua_tonumber(L, index++)); - } - - template <> - char PopPrimitive(lua_State* L, int& index) - { - return static_cast(lua_tonumber(L, index++)); - } - - template <> - unsigned char PopPrimitive(lua_State* L, int& index) - { - return static_cast(lua_tonumber(L, index++)); - } - - template <> - int64_t PopPrimitive(lua_State* L, int& index) - { - return static_cast(lua_tonumber(L, index++)); - } - - template <> - uint64_t PopPrimitive(lua_State* L, int& index) - { - return static_cast(lua_tonumber(L, index++)); - } - - template <> - float PopPrimitive(lua_State* L, int& index) - { - return static_cast(lua_tonumber(L, index++)); - } - - template <> - double PopPrimitive(lua_State* L, int& index) - { - return static_cast(lua_tonumber(L, index++)); - } - template <> bool PopPrimitive(lua_State* L, int& index) { @@ -100,4 +40,12 @@ namespace lua { return lua_touserdata(L, index++); } + + template<> + lua_Number PopPrimitive(lua_State* L, int& index) + { + return lua_tonumber(L, index++); + } + + // Int types aren't Poppable directly, because they need to be checked for under/overflow, NaN, inf } // namespace lua