153 lines
4.7 KiB
C++
153 lines
4.7 KiB
C++
#ifndef MODDING_HPP
|
|
#define MODDING_HPP
|
|
|
|
#include <dlfcn.h>
|
|
#include <open_engine.hpp>
|
|
#include <unistd.h>
|
|
|
|
#include <nethost.h>
|
|
#include <hostfxr.h>
|
|
#include <coreclr_delegates.h>
|
|
|
|
class Modding : public OpenEngine::Layer
|
|
{
|
|
public:
|
|
Modding()
|
|
: OpenEngine::Layer("modding")
|
|
{
|
|
};
|
|
~Modding()
|
|
{
|
|
};
|
|
|
|
void* get_export(void* sample_lib, const char* name) {
|
|
// dlsym is the Linux version of GetProcAddress
|
|
void* f = dlsym(sample_lib, name);
|
|
if (!f) {
|
|
OE_ERROR("Failed to find symbol: {} Error: {}", name, dlerror());
|
|
}
|
|
return f;
|
|
};
|
|
|
|
// Using the nethost library, discover the location of hostfxr and get exports
|
|
bool load_hostfxr()
|
|
{
|
|
// Pre-allocate a large buffer for the path to hostfxr
|
|
char_t buffer[250];
|
|
size_t buffer_size = sizeof(buffer) / sizeof(char_t);
|
|
int rc = get_hostfxr_path(buffer, &buffer_size, nullptr);
|
|
if (rc != 0)
|
|
return false;
|
|
|
|
// Load hostfxr and get desired exports
|
|
auto* lib = dlopen(buffer, RTLD_NOW);
|
|
init_fptr = (hostfxr_initialize_for_runtime_config_fn)get_export(lib, "hostfxr_initialize_for_runtime_config");
|
|
get_delegate_fptr = (hostfxr_get_runtime_delegate_fn)get_export(lib, "hostfxr_get_runtime_delegate");
|
|
close_fptr = (hostfxr_close_fn)get_export(lib, "hostfxr_close");
|
|
|
|
return (init_fptr && get_delegate_fptr && close_fptr);
|
|
};
|
|
|
|
load_assembly_and_get_function_pointer_fn get_dotnet_load_assembly(const char_t *config_path)
|
|
{
|
|
// Load .NET Core
|
|
void *load_assembly_and_get_function_pointer = nullptr;
|
|
hostfxr_handle cxt = nullptr;
|
|
int rc = init_fptr(config_path, nullptr, &cxt);
|
|
if (rc != 0 || cxt == nullptr)
|
|
{
|
|
OE_ERROR("Init failed");
|
|
close_fptr(cxt);
|
|
return nullptr;
|
|
}
|
|
|
|
// Get the load assembly function pointer
|
|
rc = get_delegate_fptr(
|
|
cxt,
|
|
hdt_load_assembly_and_get_function_pointer,
|
|
&load_assembly_and_get_function_pointer);
|
|
if (rc != 0 || load_assembly_and_get_function_pointer == nullptr)
|
|
OE_ERROR("Get delegate failed");
|
|
|
|
close_fptr(cxt);
|
|
return (load_assembly_and_get_function_pointer_fn)load_assembly_and_get_function_pointer;
|
|
}
|
|
|
|
component_entry_point_fn LoadMethod(const char* method)
|
|
{
|
|
component_entry_point_fn method_ptr;
|
|
|
|
int rc = load_assembly_and_get_function_pointer(
|
|
dotnet_lib_path,
|
|
dotnet_type,
|
|
method,
|
|
UNMANAGEDCALLERSONLY_METHOD /*delegate_type_name*/,
|
|
nullptr,
|
|
(void**)&method_ptr);
|
|
|
|
if (rc != 0) {
|
|
OE_ERROR("Failed to load method {}", method);
|
|
return nullptr;
|
|
}
|
|
|
|
return method_ptr;
|
|
}
|
|
|
|
void OnAttach() override
|
|
{
|
|
load_hostfxr();
|
|
|
|
load_assembly_and_get_function_pointer = get_dotnet_load_assembly("assets/scripts/mod_loader.runtimeconfig.json");
|
|
component_entry_point_fn init = LoadMethod("Init");
|
|
|
|
init(nullptr, 0);
|
|
|
|
hello = LoadMethod("Hello");
|
|
|
|
load_mod = LoadMethod("LoadMod");
|
|
load_mod(nullptr, 0);
|
|
}
|
|
|
|
void OnDetach() override
|
|
{
|
|
}
|
|
|
|
void OnUpdate() override
|
|
{
|
|
static float time = 0;
|
|
|
|
time += OpenEngine::Time::DeltaTime();
|
|
|
|
if (time >= 1) {
|
|
hello(nullptr, 0);
|
|
time = 0;
|
|
}
|
|
}
|
|
|
|
void OnEvent(OpenEngine::Event& event) override
|
|
{
|
|
//OpenEngine::EventDispatcher dispatcher(event);
|
|
|
|
//dispatcher.Dispatch<OpenEngine::KeyPressedEvent>(BIND_EVENT_FN(Sandbox2DLayer::StopRunning));
|
|
}
|
|
|
|
void OnImGuiRender() override
|
|
{
|
|
}
|
|
|
|
private:
|
|
hostfxr_initialize_for_runtime_config_fn init_fptr;
|
|
hostfxr_get_runtime_delegate_fn get_delegate_fptr;
|
|
hostfxr_close_fn close_fptr;
|
|
load_assembly_and_get_function_pointer_fn load_assembly_and_get_function_pointer;
|
|
|
|
component_entry_point_fn hello = nullptr;
|
|
component_entry_point_fn load_mod = nullptr;
|
|
|
|
const char_t* dotnet_lib_path = "assets/scripts/mod_loader.dll";
|
|
const char_t* dotnet_type = "OpenEngine.ModLoader, mod_loader";
|
|
const char_t* dotnet_type_method = "Init";
|
|
};
|
|
|
|
#endif // MODDING_HPP
|