diff --git a/CMakeLists.txt b/CMakeLists.txt index 7b1b18e41e..3a69f28c75 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -477,6 +477,7 @@ if (NOT WIN32) endif() # C++ library binding to Lua +add_compile_definitions(SOL_ALL_SAFETIES_ON) set(SOL_INCLUDE_DIR ${OpenMW_SOURCE_DIR}/extern/sol3) set(SOL_CONFIG_DIR ${OpenMW_SOURCE_DIR}/extern/sol_config) diff --git a/components/lua/luastate.hpp b/components/lua/luastate.hpp index aea1e32590..f14fc44867 100644 --- a/components/lua/luastate.hpp +++ b/components/lua/luastate.hpp @@ -232,16 +232,36 @@ namespace LuaUtil } } + // work around for a (likely) sol3 bug + // when the index meta method throws, simply calling table.get crashes instead of re-throwing the error + template + sol::object safe_get(const sol::table& table, const Key& key) + { + auto index = table.traverse_raw_get>( + sol::metatable_key, sol::meta_function::index); + if (index) + { + sol::protected_function_result result = index.value()(table, key); + if (result.valid()) + return result.get(); + else + throw result.get(); + } + else + return table.raw_get(key); + } + // getFieldOrNil(table, "a", "b", "c") returns table["a"]["b"]["c"] or nil if some of the fields doesn't exist. template sol::object getFieldOrNil(const sol::object& table, std::string_view first, const Str&... str) { if (!table.is()) return sol::nil; + sol::object value = safe_get(table.as(), first); if constexpr (sizeof...(str) == 0) - return table.as()[first]; + return value; else - return getFieldOrNil(table.as()[first], str...); + return getFieldOrNil(value, str...); } // String representation of a Lua object. Should be used for debugging/logging purposes only.