Skip to content

Commit

Permalink
Merge pull request #603 from psiberx/master
Browse files Browse the repository at this point in the history
Footsteps fix, improved error reporting, direct global functions
  • Loading branch information
Yamashi authored Aug 26, 2021
2 parents 198e6a5 + 5355d73 commit 69765e5
Show file tree
Hide file tree
Showing 6 changed files with 101 additions and 23 deletions.
44 changes: 32 additions & 12 deletions src/reverse/RTTIHelper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<RTTIHelper> s_pInstance{ nullptr };

Expand Down Expand Up @@ -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<std::shared_ptr<spdlog::logger>>();
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<std::shared_ptr<spdlog::logger>>();
logger->error("Error: {}", errorMessage);
}
}

return result;
Expand All @@ -400,7 +408,7 @@ sol::function RTTIHelper::MakeInvokableOverload(std::map<uint64_t, RED4ext::CBas
for (const auto& cFunc : aOverloadedFuncs)
variants.emplace_back(cFunc.second);

return MakeSolFunction(luaState, [this, variants](sol::variadic_args aArgs, sol::this_environment aEnv) mutable -> 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();
Expand Down Expand Up @@ -429,18 +437,30 @@ sol::function RTTIHelper::MakeInvokableOverload(std::map<uint64_t, RED4ext::CBas
}
}

const sol::environment cEnv = aEnv;
auto logger = cEnv["__logger"].get<std::shared_ptr<spdlog::logger>>();
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<std::shared_ptr<spdlog::logger>>();

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<std::shared_ptr<spdlog::logger>>();
logger->error("Error: {}", errorMessage);
}

return {};
});
}
Expand Down
21 changes: 21 additions & 0 deletions src/reverse/RTTIMapper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ void RTTIMapper::Register()

RegisterSimpleTypes(luaState, luaGlobal);
RegisterDirectTypes(luaState, luaGlobal, pRtti);
RegisterDirectGlobals(luaGlobal, pRtti);
RegisterScriptAliases(luaGlobal, pRtti);
RegisterSpecialAccessors(luaState, luaGlobal);
}
Expand Down Expand Up @@ -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) {
Expand Down
23 changes: 23 additions & 0 deletions src/reverse/RTTIMapper.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down
2 changes: 1 addition & 1 deletion src/reverse/Type.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -277,7 +277,7 @@ sol::object ClassType::Index_Impl(const std::string& acName, sol::this_environme
{
const sol::environment cEnv = aThisEnv;
std::shared_ptr<spdlog::logger> logger = cEnv["__logger"].get<std::shared_ptr<spdlog::logger>>();
logger->error("Error: {} not found in {}.", acName, GetName());
logger->warn("Warning: {} not found in {}.", acName, GetName());
return sol::nil;
}

Expand Down
29 changes: 21 additions & 8 deletions src/scripting/Scripting.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@
#include <RED4ext/Dump/Reflection.hpp>
#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)
Expand Down Expand Up @@ -263,8 +265,9 @@ void Scripting::PostInitialize()
};

luaVm.new_usertype<CName>("CName",
sol::constructors<CName(const std::string&), CName(uint32_t), CName(uint32_t, uint32_t),
sol::constructors<CName(const std::string&), CName(uint64_t), CName(uint32_t, uint32_t),
CName(const CName&), CName()>(),
sol::call_constructor, sol::constructors<CName(const std::string&), CName(uint64_t)>(),
sol::meta_function::to_string, &CName::ToString,
sol::meta_function::equal_to, &CName::operator==,
"hash_lo", &CName::hash_lo,
Expand All @@ -284,6 +287,7 @@ void Scripting::PostInitialize()
luaVm.new_usertype<TweakDBID>("TweakDBID",
sol::constructors<TweakDBID(const std::string&), TweakDBID(const TweakDBID&, const std::string&),
TweakDBID(uint32_t, uint8_t), TweakDBID(const TweakDBID&), TweakDBID()>(),
sol::call_constructor, sol::constructors<TweakDBID(const std::string&)>(),
sol::meta_function::to_string, &TweakDBID::ToString,
sol::meta_function::equal_to, &TweakDBID::operator==,
sol::meta_function::addition, &TweakDBID::operator+,
Expand Down Expand Up @@ -483,7 +487,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);
}
Expand Down Expand Up @@ -568,14 +572,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)
Expand All @@ -585,15 +589,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<spdlog::logger> logger = cEnv["__logger"].get<std::shared_ptr<spdlog::logger>>();
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<spdlog::logger> logger = cEnv["__logger"].get<std::shared_ptr<spdlog::logger>>();
logger->error("Error: {}", errorMessage);
}

return sol::nil;
}
Expand Down
5 changes: 3 additions & 2 deletions src/scripting/Scripting.h
Original file line number Diff line number Diff line change
Expand Up @@ -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<sol::state, std::recursive_mutex> m_lua;
Expand Down

0 comments on commit 69765e5

Please sign in to comment.