Skip to content

Commit

Permalink
Lua: Add UObject:DANGEROUS_call_member_virtual(args...)
Browse files Browse the repository at this point in the history
  • Loading branch information
praydog committed Oct 12, 2024
1 parent cdf99f7 commit fcceb47
Showing 1 changed file with 48 additions and 0 deletions.
48 changes: 48 additions & 0 deletions lua-api/lib/src/ScriptContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -465,6 +465,54 @@ int ScriptContext::setup_bindings() {
"call", [](sol::this_state s, uevr::API::UObject* self, const std::wstring& name, sol::variadic_args args) -> sol::object {
return lua::utility::call_function(s, self, name, args);
},
"DANGEROUS_call_member_virtual", [](sol::this_state s, uevr::API::UObject* self, size_t index, sol::variadic_args args) -> sol::object {
if (args.size() > 3) {
throw sol::error("DANGEROUS_call_member_virtual: Too many arguments (max 3)");
}

if (index > 1000) { // Yeah right
throw sol::error("DANGEROUS_call_member_virtual: Index too high");
}

void* args_ptr[3]{};

for (size_t i = 0; i < args.size(); ++i) {
if (args[i].is<sol::nil_t>()) {
args_ptr[i] = nullptr;
continue;
}

// Only support basic arguments for now until we can test this more
if (args[i].is<uevr::API::UObject*>()) {
args_ptr[i] = args[i].as<uevr::API::UObject*>();
} else {
// We dont support floats for now because we'd need to JIT the function call
throw sol::error("DANGEROUS_call_member_virtual: Invalid argument type");
}
}

void* result{};
using fn_t = void*(*)(uevr::API::UObject*, void*, void*, void*);
const auto vtable = *(void***)self;
if (vtable == nullptr) {
throw sol::error("DANGEROUS_call_member_virtual: Object has no vtable");
}

const auto fn = (fn_t)vtable[index];
if (fn == nullptr) {
throw sol::error("DANGEROUS_call_member_virtual: Function not found in vtable");
}

try {
// We need to wrap this in a try-catch block because who knows what the function does
result = fn(self, args_ptr[0], args_ptr[1], args_ptr[2]);
} catch (...) {
throw sol::error("DANGEROUS_call_member_virtual: Exception thrown");
return sol::make_object(s, sol::lua_nil);
}

return sol::make_object(s, result); // TODO: convert?
},
sol::meta_function::index, [](sol::this_state s, uevr::API::UObject* self, sol::object index_obj) -> sol::object {
if (!index_obj.is<std::string>()) {
return sol::make_object(s, sol::lua_nil);
Expand Down

0 comments on commit fcceb47

Please sign in to comment.