Skip to content

Commit 5f08f33

Browse files
committed
feat(Lua): NotifyOnNewObject for unloaded classes
1 parent 12c6627 commit 5f08f33

File tree

2 files changed

+42
-13
lines changed

2 files changed

+42
-13
lines changed

UE4SS/include/Mod/LuaMod.hpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,8 @@ namespace RC
122122
struct LuaCancellableCallbackData
123123
{
124124
const LuaMadeSimple::Lua* lua;
125-
Unreal::UClass* instance_of_class;
125+
Unreal::FName instance_class_name{};
126+
Unreal::FName instance_class_outer_name{};
126127
int32_t lua_callback_function_ref{};
127128
int32_t lua_callback_thread_ref{};
128129
};

UE4SS/src/Mod/LuaMod.cpp

Lines changed: 40 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2290,9 +2290,32 @@ No overload found for function 'NotifyOnNewObject'.
22902290

22912291
const auto func_ref = hook_lua->registry().make_ref();
22922292

2293-
Unreal::UClass* instance_of_class = Unreal::UObjectGlobals::StaticFindObject<Unreal::UClass*>(nullptr, nullptr, class_name);
2293+
if (class_name.contains(STR(' ')))
2294+
{
2295+
lua.throw_error(fmt::format("Param #1 for NotifyOnNewObject cannot contain spaces; Param value: '{}'", to_utf8_string(class_name)));
2296+
}
2297+
2298+
const auto name_parts = explode_by_occurrence(class_name, STR('.'));
2299+
if (name_parts.size() < 2)
2300+
{
2301+
lua.throw_error(fmt::format("Param #1 for NotifyOnNewObject must contain at least two parts; Param value: '{}'", to_utf8_string(class_name)));
2302+
}
2303+
2304+
auto class_fname = Unreal::FName(name_parts.back(), Unreal::FNAME_Find);
2305+
if (class_fname == Unreal::NAME_None)
2306+
{
2307+
class_fname = Unreal::FName(name_parts.back(), Unreal::FNAME_Add);
2308+
}
2309+
2310+
auto class_outer_fname = Unreal::FName(name_parts.front(), Unreal::FNAME_Find);
2311+
if (class_outer_fname == Unreal::NAME_None)
2312+
{
2313+
class_outer_fname = Unreal::FName(name_parts.front(), Unreal::FNAME_Add);
2314+
}
2315+
2316+
LuaMod::m_static_construct_object_lua_callbacks.emplace_back(hook_lua, class_fname, class_outer_fname, func_ref, thread_ref);
22942317

2295-
LuaMod::m_static_construct_object_lua_callbacks.emplace_back(LuaMod::LuaCancellableCallbackData{hook_lua, instance_of_class, func_ref, thread_ref});
2318+
Output::send<LogLevel::Verbose>(STR("[NotifyOnNewObject] Registered notification for {}\n"), class_name);
22962319

22972320
return 0;
22982321
});
@@ -5894,19 +5917,21 @@ No overload found for function 'FPackageName:IsValidLongPackageName'.
58945917

58955918
Unreal::Hook::RegisterStaticConstructObjectPostCallback([](const Unreal::FStaticConstructObjectParameters&, Unreal::UObject* constructed_object) {
58965919
return TRY([&] {
5897-
Unreal::UStruct* object_class = constructed_object->GetClassPrivate();
5898-
while (object_class)
5899-
{
5900-
std::erase_if(m_static_construct_object_lua_callbacks, [&](auto& callback_data) -> bool {
5920+
auto attempt_to_call_callback = [constructed_object](const Unreal::UStruct* comparison_class) {
5921+
std::erase_if(m_static_construct_object_lua_callbacks, [&](const LuaCancellableCallbackData& callback_data) -> bool {
59015922
bool cancel = false;
5902-
if (callback_data.instance_of_class == object_class)
5923+
bool match = false;
5924+
if (comparison_class->GetNamePrivate().Equals(callback_data.instance_class_name) && comparison_class->GetOuterPrivate()->GetNamePrivate().Equals(callback_data.instance_class_outer_name))
5925+
{
5926+
match = true;
5927+
}
5928+
5929+
if (match)
59035930
{
59045931
callback_data.lua->registry().get_function_ref(callback_data.lua_callback_function_ref);
59055932
LuaType::auto_construct_object(*callback_data.lua, constructed_object);
59065933
callback_data.lua->call_function(1, 1);
5907-
59085934
cancel = callback_data.lua->is_bool(-1) && callback_data.lua->get_bool(-1);
5909-
59105935
if (cancel)
59115936
{
59125937
// Release the thread_ref to GC.
@@ -5916,10 +5941,13 @@ No overload found for function 'FPackageName:IsValidLongPackageName'.
59165941

59175942
return cancel;
59185943
});
5919-
5920-
object_class = object_class->GetSuperStruct();
5944+
};
5945+
Unreal::UStruct* object_class = constructed_object->GetClassPrivate();
5946+
attempt_to_call_callback(object_class);
5947+
for (const auto comparison_class : Unreal::TSuperStructRange(object_class))
5948+
{
5949+
attempt_to_call_callback(comparison_class);
59215950
}
5922-
59235951
return constructed_object;
59245952
});
59255953
});

0 commit comments

Comments
 (0)