#ifndef MODDING_HPP #define MODDING_HPP #include #include #include #include #include #include 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(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