From 2bac8776d13441825442427b665ca82f79fcd3fc Mon Sep 17 00:00:00 2001 From: pv Date: Wed, 25 Aug 2021 20:59:28 +0300 Subject: [PATCH 1/4] Fix disappearing footsteps --- src/scripting/Scripting.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/scripting/Scripting.cpp b/src/scripting/Scripting.cpp index 59ccc479..c6b29180 100644 --- a/src/scripting/Scripting.cpp +++ b/src/scripting/Scripting.cpp @@ -483,7 +483,7 @@ void Scripting::RegisterOverrides() registerInputListener(aSelf, aSelf); }; - m_override.Override("PlayerPuppet", "EnableUIBlackboardListener", "EnableUIBlackboardListener", false, luaVm["RegisterGlobalInputListener"], sol::nil, false); + m_override.Override("PlayerPuppet", "GracePeriodAfterSpawn", "GracePeriodAfterSpawn", false, luaVm["RegisterGlobalInputListener"], sol::nil, true); m_override.Override("PlayerPuppet", "OnDetach", "OnDetach", false, sol::nil, sol::nil, true); m_override.Override("QuestTrackerGameController", "OnUninitialize", "OnUninitialize", false, sol::nil, sol::nil, true); } From ce34101103f0c473861a0c354b770e9d7899e442 Mon Sep 17 00:00:00 2001 From: pv Date: Thu, 26 Aug 2021 01:28:34 +0300 Subject: [PATCH 2/4] Throw lua errors from RTTI calls --- src/reverse/RTTIHelper.cpp | 44 +++++++++++++++++++++++++++---------- src/reverse/Type.cpp | 2 +- src/scripting/Scripting.cpp | 23 ++++++++++++++----- src/scripting/Scripting.h | 5 +++-- 4 files changed, 53 insertions(+), 21 deletions(-) diff --git a/src/reverse/RTTIHelper.cpp b/src/reverse/RTTIHelper.cpp index 0f6144a8..babfc91a 100644 --- a/src/reverse/RTTIHelper.cpp +++ b/src/reverse/RTTIHelper.cpp @@ -11,6 +11,7 @@ static constexpr const bool s_cEnableOverloads = true; static constexpr const bool s_cLogAllOverloadVariants = true; +static constexpr const bool s_cThrowLuaErrors = true; static std::unique_ptr s_pInstance{ nullptr }; @@ -372,18 +373,25 @@ sol::function RTTIHelper::MakeInvokableFunction(RED4ext::CBaseFunction* apFunc) auto lockedState = m_lua.Lock(); auto& luaState = lockedState.Get(); - return MakeSolFunction(luaState, [this, apFunc](sol::variadic_args aArgs, sol::this_environment aEnv) -> sol::variadic_results { + return MakeSolFunction(luaState, [this, apFunc](sol::variadic_args aArgs, sol::this_state aState, sol::this_environment aEnv) -> sol::variadic_results { uint64_t argOffset = 0; RED4ext::ScriptInstance pHandle = ResolveHandle(apFunc, aArgs, argOffset); - std::string error; - auto result = ExecuteFunction(apFunc, pHandle, aArgs, argOffset, error); + std::string errorMessage; + auto result = ExecuteFunction(apFunc, pHandle, aArgs, argOffset, errorMessage); - if (!error.empty()) + if (!errorMessage.empty()) { - const sol::environment cEnv = aEnv; - auto logger = cEnv["__logger"].get>(); - logger->error("Error: {}", error); + if constexpr (s_cThrowLuaErrors) + { + luaL_error(aState, errorMessage.c_str()); + } + else + { + const sol::environment cEnv = aEnv; + auto logger = cEnv["__logger"].get>(); + logger->error("Error: {}", errorMessage); + } } return result; @@ -400,7 +408,7 @@ sol::function RTTIHelper::MakeInvokableOverload(std::map sol::variadic_results { + return MakeSolFunction(luaState, [this, variants](sol::variadic_args aArgs, sol::this_state aState, sol::this_environment aEnv) mutable -> sol::variadic_results { for (auto variant = variants.begin(); variant != variants.end(); variant++) { variant->lastError.clear(); @@ -429,18 +437,30 @@ sol::function RTTIHelper::MakeInvokableOverload(std::map>(); - logger->error("Error: No matching overload of '{}' function.", variants.begin()->func->shortName.ToString()); - if constexpr (s_cLogAllOverloadVariants) { + const sol::environment cEnv = aEnv; + auto logger = cEnv["__logger"].get>(); + for (auto variant = variants.begin(); variant != variants.end(); variant++) logger->info("{}: {}", variant->func->fullName.ToString(), variant->lastError); logger->flush(); } + std::string errorMessage = fmt::format("No matching overload of '{}' function.", variants.begin()->func->shortName.ToString()); + + if constexpr (s_cThrowLuaErrors) + { + luaL_error(aState, errorMessage.c_str()); + } + else + { + const sol::environment cEnv = aEnv; + auto logger = cEnv["__logger"].get>(); + logger->error("Error: {}", errorMessage); + } + return {}; }); } diff --git a/src/reverse/Type.cpp b/src/reverse/Type.cpp index 970517a0..c0efffaf 100644 --- a/src/reverse/Type.cpp +++ b/src/reverse/Type.cpp @@ -277,7 +277,7 @@ sol::object ClassType::Index_Impl(const std::string& acName, sol::this_environme { const sol::environment cEnv = aThisEnv; std::shared_ptr logger = cEnv["__logger"].get>(); - logger->error("Error: {} not found in {}.", acName, GetName()); + logger->warn("Warning: {} not found in {}.", acName, GetName()); return sol::nil; } diff --git a/src/scripting/Scripting.cpp b/src/scripting/Scripting.cpp index c6b29180..efcbb100 100644 --- a/src/scripting/Scripting.cpp +++ b/src/scripting/Scripting.cpp @@ -31,6 +31,8 @@ #include #endif +static constexpr const bool s_cThrowLuaErrors = true; + static RTTILocator s_stringType{RED4ext::FNV1a("String")}; Scripting::Scripting(const Paths& aPaths, VKBindings& aBindings, D3D12& aD3D12, Options& aOptions) @@ -568,14 +570,14 @@ std::string Scripting::GetGlobalName() const noexcept return m_global; } -sol::object Scripting::Index(const std::string& acName, sol::this_environment aThisEnv) +sol::object Scripting::Index(const std::string& acName, sol::this_state aState, sol::this_environment aEnv) { if (const auto itor = m_properties.find(acName); itor != m_properties.end()) { return itor->second; } - return InternalIndex(acName, aThisEnv); + return InternalIndex(acName, aState, aEnv); } sol::object Scripting::NewIndex(const std::string& acName, sol::object aParam) @@ -585,15 +587,24 @@ sol::object Scripting::NewIndex(const std::string& acName, sol::object aParam) return property; } -sol::protected_function Scripting::InternalIndex(const std::string& acName, sol::this_environment aThisEnv) +sol::protected_function Scripting::InternalIndex(const std::string& acName, sol::this_state aState, sol::this_environment aEnv) { auto func = RTTIHelper::Get().ResolveFunction(acName); if (!func) { - const sol::environment cEnv = aThisEnv; - std::shared_ptr logger = cEnv["__logger"].get>(); - logger->error("Error: Function {} not found or is not a global.", acName); + std::string errorMessage = fmt::format("Function {} is not a GameInstance member and is not a global.", acName); + + if constexpr (s_cThrowLuaErrors) + { + luaL_error(aState, errorMessage.c_str()); + } + else + { + const sol::environment cEnv = aEnv; + std::shared_ptr logger = cEnv["__logger"].get>(); + logger->error("Error: {}", errorMessage); + } return sol::nil; } diff --git a/src/scripting/Scripting.h b/src/scripting/Scripting.h index d59125a6..be59c999 100644 --- a/src/scripting/Scripting.h +++ b/src/scripting/Scripting.h @@ -42,10 +42,11 @@ struct Scripting protected: void RegisterOverrides(); - sol::object Index(const std::string& acName, sol::this_environment aThisEnv); + sol::object Index(const std::string& acName, sol::this_state aState, sol::this_environment aEnv); sol::object NewIndex(const std::string& acName, sol::object aParam); sol::object GetSingletonHandle(const std::string& acName, sol::this_environment aThisEnv); - sol::protected_function InternalIndex(const std::string& acName, sol::this_environment aThisEnv); + sol::protected_function InternalIndex(const std::string& acName, sol::this_state aState, + sol::this_environment aEnv); private: TiltedPhoques::Lockable m_lua; From b2c6dfcbf38bc6923662745f71fc7d7ad7d1f05b Mon Sep 17 00:00:00 2001 From: pv Date: Thu, 26 Aug 2021 01:49:09 +0300 Subject: [PATCH 3/4] Add direct access for global functions --- src/reverse/RTTIMapper.cpp | 21 +++++++++++++++++++++ src/reverse/RTTIMapper.h | 23 +++++++++++++++++++++++ 2 files changed, 44 insertions(+) diff --git a/src/reverse/RTTIMapper.cpp b/src/reverse/RTTIMapper.cpp index c7922083..57963a57 100644 --- a/src/reverse/RTTIMapper.cpp +++ b/src/reverse/RTTIMapper.cpp @@ -33,6 +33,7 @@ void RTTIMapper::Register() RegisterSimpleTypes(luaState, luaGlobal); RegisterDirectTypes(luaState, luaGlobal, pRtti); + RegisterDirectGlobals(luaGlobal, pRtti); RegisterScriptAliases(luaGlobal, pRtti); RegisterSpecialAccessors(luaState, luaGlobal); } @@ -120,6 +121,26 @@ void RTTIMapper::RegisterDirectTypes(sol::state& aLuaState, sol::table& aLuaGlob }); } +void RTTIMapper::RegisterDirectGlobals(sol::table& aLuaGlobal, RED4ext::CRTTISystem* apRtti) +{ + apRtti->funcs.for_each([&aLuaGlobal](RED4ext::CName aOrigName, RED4ext::CGlobalFunction* apFunc) { + const std::string cShortName = apFunc->shortName.ToString(); + const FuncFlags cFlags = *(FuncFlags*)(&apFunc->flags); + + if (aLuaGlobal[cShortName] == sol::nil && !cFlags.isExec) + { + const std::string cFullName = apFunc->fullName.ToString(); + const auto cIsClassFunc = cFullName.find("::") != std::string::npos; + const auto cIsOperatorFunc = cShortName.find(";") != std::string::npos; + + if (!cIsClassFunc && !cIsOperatorFunc) + { + aLuaGlobal[cShortName] = RTTIHelper::Get().ResolveFunction(cShortName); + } + } + }); +} + void RTTIMapper::RegisterScriptAliases(sol::table& aLuaGlobal, RED4ext::CRTTISystem* apRtti) { apRtti->scriptToNative.for_each([&aLuaGlobal](RED4ext::CName aScriptName, RED4ext::CName aNativeName) { diff --git a/src/reverse/RTTIMapper.h b/src/reverse/RTTIMapper.h index 557cb61b..f3164437 100644 --- a/src/reverse/RTTIMapper.h +++ b/src/reverse/RTTIMapper.h @@ -13,8 +13,31 @@ struct RTTIMapper private: + struct FuncFlags + { + uint32_t isNative : 1; // 00 + uint32_t isStatic : 1; // 01 + uint32_t isFinal : 1; // 02 + uint32_t isEvent : 1; // 03 + uint32_t isExec : 1; // 04 + uint32_t isUndefinedBody : 1; // 05 Unconfirmed (unset for scripted funcs without body) + uint32_t isTimer : 1; // 06 Unconfirmed + uint32_t isPrivate : 1; // 07 + uint32_t isProtected : 1; // 08 + uint32_t isPublic : 1; // 09 + uint32_t b11 : 1; // 0A + uint32_t b12 : 1; // 0B + uint32_t b13 : 1; // 0C + uint32_t isConst : 1; // 0D + uint32_t isQuest : 1; // 0E + uint32_t isThreadsafe : 1; // 0F + uint32_t b16 : 16; + }; + RED4EXT_ASSERT_SIZE(FuncFlags, 0x4); + void RegisterSimpleTypes(sol::state& aLuaState, sol::table& aLuaGlobal); void RegisterDirectTypes(sol::state& aLuaState, sol::table& aLuaGlobal, RED4ext::CRTTISystem* apRtti); + void RegisterDirectGlobals(sol::table& aLuaGlobal, RED4ext::CRTTISystem* apRtti); void RegisterScriptAliases(sol::table& aLuaGlobal, RED4ext::CRTTISystem* apRtti); void RegisterSpecialAccessors(sol::state& aLuaState, sol::table& aLuaGlobal); From 5355d738a29205d8de7d797b1873a2c537c7f71b Mon Sep 17 00:00:00 2001 From: pv Date: Thu, 26 Aug 2021 01:49:57 +0300 Subject: [PATCH 4/4] Add alternative syntax for CName and TweakDBID --- src/scripting/Scripting.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/scripting/Scripting.cpp b/src/scripting/Scripting.cpp index efcbb100..5a03a8f1 100644 --- a/src/scripting/Scripting.cpp +++ b/src/scripting/Scripting.cpp @@ -265,8 +265,9 @@ void Scripting::PostInitialize() }; luaVm.new_usertype("CName", - sol::constructors(), + sol::call_constructor, sol::constructors(), sol::meta_function::to_string, &CName::ToString, sol::meta_function::equal_to, &CName::operator==, "hash_lo", &CName::hash_lo, @@ -286,6 +287,7 @@ void Scripting::PostInitialize() luaVm.new_usertype("TweakDBID", sol::constructors(), + sol::call_constructor, sol::constructors(), sol::meta_function::to_string, &TweakDBID::ToString, sol::meta_function::equal_to, &TweakDBID::operator==, sol::meta_function::addition, &TweakDBID::operator+,