From 0c804cfc1e44d405833adb833331a08b2adb240d Mon Sep 17 00:00:00 2001 From: yamashi Date: Mon, 21 Dec 2020 17:49:24 +0100 Subject: [PATCH] Added member function script calling --- src/reverse/Scripting.cpp | 71 ++++++++++++++++++++++----------------- src/reverse/Scripting.h | 13 +++++-- src/reverse/Type.cpp | 7 ++-- src/reverse/Type.h | 7 +++- 4 files changed, 62 insertions(+), 36 deletions(-) diff --git a/src/reverse/Scripting.cpp b/src/reverse/Scripting.cpp index fafcd3f9..7e82f642 100644 --- a/src/reverse/Scripting.cpp +++ b/src/reverse/Scripting.cpp @@ -24,9 +24,14 @@ Scripting::Scripting() sol::meta_function::new_index, &Type::NewIndex); m_lua["Game"] = this; - m_lua["GetType"] = [this](const std::string& acName) + m_lua["CreateSingletonHandle"] = [this](const std::string& acName) { - return this->GetType(acName); + return this->CreateSingletonHandle(acName); + }; + + m_lua["CreateHandle"] = [this](const std::string& acName, RED4ext::REDreverse::Scripting::IScriptable* apHandle) + { + return this->CreateHandle(acName, apHandle); }; m_lua["print"] = [](sol::variadic_args args, sol::this_environment env, sol::this_state L) @@ -82,7 +87,12 @@ sol::object Scripting::NewIndex(const std::string& acName, sol::object aParam) return property; } -sol::object Scripting::GetType(const std::string& acName) +sol::object Scripting::CreateSingletonHandle(const std::string& acName) +{ + return CreateHandle(acName, nullptr); +} + +sol::object Scripting::CreateHandle(const std::string& acName, RED4ext::REDreverse::Scripting::IScriptable* apHandle) { auto itor = m_systems.find(acName); if (itor != std::end(m_systems)) @@ -90,14 +100,13 @@ sol::object Scripting::GetType(const std::string& acName) auto* pRtti = RED4ext::REDreverse::CRTTISystem::Get(); auto* pType = pRtti->GetType(RED4ext::FNV1a(acName)); - if(!pType) + if (!pType) { Overlay::Get().Log("Type '" + acName + "' not found or is not initialized yet."); return make_object(m_lua, nullptr); } - auto result = m_systems.emplace(std::make_pair(acName, Type{ m_lua, pType, acName })); - + auto result = m_systems.emplace(std::make_pair(acName, Type{ m_lua, pType, acName, apHandle })); return make_object(m_lua, result.first->second); } @@ -107,18 +116,18 @@ sol::protected_function Scripting::InternalIndex(const std::string& acName) auto obj = make_object(state, [this, name = acName](sol::variadic_args args, sol::this_environment env, sol::this_state L) { std::string result; - bool code = this->Execute(name, args, env, L, result); + auto code = this->Execute(name, args, env, L, result); if(!code) { Overlay::Get().Log("Error: " + result); } - return std::make_tuple(code, result); + return code; }); return NewIndex(acName, std::move(obj)); } -bool Scripting::Execute(const std::string& aFuncName, sol::variadic_args aArgs, sol::this_environment env, sol::this_state L, std::string& aReturnMessage) +sol::object Scripting::Execute(const std::string& aFuncName, sol::variadic_args aArgs, sol::this_environment env, sol::this_state L, std::string& aReturnMessage) { static RED4ext::REDfunc CNamePool_Get({ 0x48, 0x83, 0xEC, 0x38, 0x48,0x8B,0x11,0x48,0x8D,0x4C,0x24,0x20,0xE8 }, 1); @@ -130,7 +139,8 @@ bool Scripting::Execute(const std::string& aFuncName, sol::variadic_args aArgs, if (!pFunc) { aReturnMessage = "Function '" + aFuncName + "' not found or is not a global."; - return false; + + return make_object(m_lua, nullptr); } if (pFunc->params.size - 1 != aArgs.size()) @@ -138,7 +148,8 @@ bool Scripting::Execute(const std::string& aFuncName, sol::variadic_args aArgs, aReturnMessage = "Function '" + aFuncName + "' expects " + std::to_string(pFunc->params.size - 1) + " parameters, not " + std::to_string(aArgs.size()) + "."; - return false; + + return make_object(m_lua, nullptr); } auto engine = RED4ext::REDreverse::CGameEngine::Get(); @@ -149,7 +160,7 @@ bool Scripting::Execute(const std::string& aFuncName, sol::variadic_args aArgs, args[0].type = *reinterpret_cast(pFunc->params.unk0[0]); args[0].value = &unk10; - const bool hasReturnType = (pFunc->returnType) != nullptr && (*pFunc->returnType) != nullptr; + const bool hasReturnType = (pFunc->returnType) != nullptr && (*pFunc->returnType) != nullptr && (*pFunc->returnType)->GetType() == RED4ext::REDreverse::RTTIType::Handle; for (auto i = 0; i < aArgs.size(); ++i) { @@ -182,27 +193,22 @@ bool Scripting::Execute(const std::string& aFuncName, sol::variadic_args aArgs, aReturnMessage = "Function '" + aFuncName + "' parameter " + std::to_string(i) + " must be " + typeName + "."; } - return false; + return make_object(m_lua, nullptr); } } - uint8_t returnBuffer[0x100]; - CStackType result; - if (hasReturnType) - { - uint64_t hash = 0; - (*pFunc->returnType)->GetName(&hash); - if (hash) - { - std::string typeName = CNamePool_Get(hash); - Overlay::Get().Log("Return type: " + typeName); - } - } - /*if (aOut) + struct Ref { - result.value = aOut; - }*/ + RED4ext::REDreverse::Scripting::IScriptable* ref{nullptr}; + uint32_t* count{nullptr}; + }; + + Ref returnBuffer; + + CStackType result; + result.value = &returnBuffer; + result.type = *pFunc->returnType; std::aligned_storage_t stackStore; auto* stack = reinterpret_cast(&stackStore); @@ -210,11 +216,14 @@ bool Scripting::Execute(const std::string& aFuncName, sol::variadic_args aArgs, static const auto cpPlayerSystem = RED4ext::FNV1a("cpPlayerSystem"); const auto* type = pRtti->GetType(cpPlayerSystem); - const auto* pScriptable = unk10->GetTypeInstance(type); + + auto pScriptable = unk10->GetTypeInstance(type); RED4ext::REDreverse::CScriptableStackFrame::Construct(stack, pScriptable, args.data(), - static_cast(args.size()), nullptr, 0); + static_cast(args.size()), hasReturnType ? &result : nullptr, 0); const auto success = pFunc->Call(stack); + if (!success) + return make_object(m_lua, nullptr); - return success; + return make_object(m_lua, returnBuffer.ref); } diff --git a/src/reverse/Scripting.h b/src/reverse/Scripting.h index 7dd459c0..0dda6418 100644 --- a/src/reverse/Scripting.h +++ b/src/reverse/Scripting.h @@ -5,6 +5,14 @@ #include "Type.h" +namespace RED4ext { + namespace REDreverse { + namespace Scripting { + struct IScriptable; + } + } +} + struct Scripting { Scripting(); @@ -17,10 +25,11 @@ struct Scripting sol::object Index(const std::string& acName); sol::object NewIndex(const std::string& acName, sol::object aParam); - sol::object GetType(const std::string& acName); + sol::object CreateSingletonHandle(const std::string& acName); + sol::object CreateHandle(const std::string& acName, RED4ext::REDreverse::Scripting::IScriptable* apHandle); sol::protected_function InternalIndex(const std::string& acName); - bool Execute(const std::string& aFuncName, sol::variadic_args args, sol::this_environment env, sol::this_state L, std::string& aReturnMessage); + sol::object Execute(const std::string& aFuncName, sol::variadic_args args, sol::this_environment env, sol::this_state L, std::string& aReturnMessage); private: sol::state m_lua; diff --git a/src/reverse/Type.cpp b/src/reverse/Type.cpp index dfd5b0a1..969eac0d 100644 --- a/src/reverse/Type.cpp +++ b/src/reverse/Type.cpp @@ -11,10 +11,11 @@ #include "RED4ext/REDreverse/Function.hpp" #include "overlay/Overlay.h" -Type::Type(sol::state_view aView, RED4ext::REDreverse::CClass* apClass, std::string aName) +Type::Type(sol::state_view aView, RED4ext::REDreverse::CClass* apClass, std::string aName, RED4ext::REDreverse::Scripting::IScriptable* apHandle) : m_lua(aView) , m_pType(apClass) , m_name(std::move(aName)) + , m_pHandle(apHandle) { } @@ -148,7 +149,9 @@ sol::object Type::Execute(RED4ext::REDreverse::CClassFunction* apFunc, const std std::aligned_storage_t stackStore; auto* stack = reinterpret_cast(&stackStore); - const auto* pScriptable = unk10->GetTypeInstance(m_pType); + auto* pScriptable = m_pHandle; + if(pScriptable == nullptr) + pScriptable = unk10->GetTypeInstance(m_pType); RED4ext::REDreverse::CScriptableStackFrame::Construct(stack, pScriptable, args.data(), static_cast(args.size()), hasReturnType ? &result : nullptr, 0); diff --git a/src/reverse/Type.h b/src/reverse/Type.h index 19779612..9674877a 100644 --- a/src/reverse/Type.h +++ b/src/reverse/Type.h @@ -5,6 +5,10 @@ namespace RED4ext { namespace REDreverse { + namespace Scripting { + struct IScriptable; + } + struct CClass; struct CClassFunction; } @@ -12,7 +16,7 @@ namespace RED4ext { struct Type { - Type(sol::state_view aView, RED4ext::REDreverse::CClass* apClass, std::string aName); + Type(sol::state_view aView, RED4ext::REDreverse::CClass* apClass, std::string aName, RED4ext::REDreverse::Scripting::IScriptable* apHandle = nullptr); sol::object Index(const std::string& acName); sol::object NewIndex(const std::string& acName, sol::object aParam); @@ -23,6 +27,7 @@ struct Type private: sol::state_view m_lua; RED4ext::REDreverse::CClass* m_pType; + RED4ext::REDreverse::Scripting::IScriptable* m_pHandle{nullptr}; std::string m_name; std::unordered_map m_properties; };