From 1883ddc9036f26dc65cf94515a0cf771c08032b6 Mon Sep 17 00:00:00 2001 From: praydog Date: Sat, 12 Oct 2024 14:04:31 -0700 Subject: [PATCH] Plugins/Lua: Add dispatch_lua_event, on_lua_event --- include/uevr/API.h | 3 ++- include/uevr/API.hpp | 5 +++++ lua-api/lib/include/ScriptContext.hpp | 32 ++++++++++++++++++++++++--- lua-api/lib/include/ScriptState.hpp | 1 + lua-api/lib/src/ScriptContext.cpp | 21 ++++++++++++++++++ lua-api/lib/src/ScriptState.cpp | 6 +++++ src/mods/LuaLoader.cpp | 10 +++++++++ src/mods/LuaLoader.hpp | 1 + src/mods/PluginLoader.cpp | 7 +++++- 9 files changed, 81 insertions(+), 5 deletions(-) diff --git a/include/uevr/API.h b/include/uevr/API.h index a46e93dd..8ea8e79e 100644 --- a/include/uevr/API.h +++ b/include/uevr/API.h @@ -36,7 +36,7 @@ SOFTWARE. #define UEVR_OUT #define UEVR_PLUGIN_VERSION_MAJOR 2 -#define UEVR_PLUGIN_VERSION_MINOR 32 +#define UEVR_PLUGIN_VERSION_MINOR 33 #define UEVR_PLUGIN_VERSION_PATCH 0 #define UEVR_RENDERER_D3D11 0 @@ -217,6 +217,7 @@ typedef struct { unsigned int (*get_persistent_dir)(wchar_t* buffer, unsigned int buffer_size); int (*register_inline_hook)(void* target, void* dst, void** original); void (*unregister_inline_hook)(int hook_id); + void (*dispatch_lua_event)(const char* event_name, const char* event_data); } UEVR_PluginFunctions; typedef struct { diff --git a/include/uevr/API.hpp b/include/uevr/API.hpp index 657a51ea..45988e29 100644 --- a/include/uevr/API.hpp +++ b/include/uevr/API.hpp @@ -105,6 +105,11 @@ class API { return result; } + void dispatch_lua_event(std::string_view event_name, std::string_view event_data) { + static const auto fn = param()->functions->dispatch_lua_event; + fn(event_name.data(), event_data.data()); + } + template void log_error(const char* format, Args... args) { m_param->functions->log_error(format, args...); } template void log_warn(const char* format, Args... args) { m_param->functions->log_warn(format, args...); } template void log_info(const char* format, Args... args) { m_param->functions->log_info(format, args...); } diff --git a/lua-api/lib/include/ScriptContext.hpp b/lua-api/lib/include/ScriptContext.hpp index b1de9b24..440fb4bd 100644 --- a/lua-api/lib/include/ScriptContext.hpp +++ b/lua-api/lib/include/ScriptContext.hpp @@ -72,24 +72,48 @@ class ScriptContext : public std::enable_shared_from_this { void script_reset() { std::scoped_lock _{m_mtx}; - for (auto& cb : m_on_script_reset_callbacks) { + for (auto& cb : m_on_script_reset_callbacks) try { handle_protected_result(cb()); + } catch (const std::exception& e) { + log("Exception in on_script_reset: " + std::string(e.what())); + } catch (...) { + log("Unknown exception in on_script_reset"); } } void frame() { std::scoped_lock _{m_mtx}; - for (auto& cb : m_on_frame_callbacks) { + for (auto& cb : m_on_frame_callbacks) try { handle_protected_result(cb()); + } catch (const std::exception& e) { + log("Exception in on_frame: " + std::string(e.what())); + } catch (...) { + log("Unknown exception in on_frame"); } } void draw_ui() { std::scoped_lock _{m_mtx}; - for (auto& cb : m_on_draw_ui_callbacks) { + for (auto& cb : m_on_draw_ui_callbacks) try { handle_protected_result(cb()); + } catch (const std::exception& e) { + log("Exception in on_draw_ui: " + std::string(e.what())); + } catch (...) { + log("Unknown exception in on_draw_ui"); + } + } + + void dispatch_event(std::string_view event_name, std::string_view event_data) { + std::scoped_lock _{m_mtx}; + + for (auto& cb : m_on_lua_event_callbacks) try { + handle_protected_result(cb(event_name, event_data)); + } catch (const std::exception& e) { + log("Exception in on_lua_event: " + std::string(e.what())); + } catch (...) { + log("Unknown exception in on_lua_event"); } } @@ -116,6 +140,7 @@ class ScriptContext : public std::enable_shared_from_this { std::vector m_on_post_calculate_stereo_view_offset_callbacks{}; std::vector m_on_pre_viewport_client_draw_callbacks{}; std::vector m_on_post_viewport_client_draw_callbacks{}; + std::vector m_on_lua_event_callbacks{}; // Custom UEVR callbacks std::vector m_on_frame_callbacks{}; @@ -146,5 +171,6 @@ class ScriptContext : public std::enable_shared_from_this { static void on_frame(); static void on_draw_ui(); static void on_script_reset(); + static void on_lua_event(std::string_view event_name, std::string_view event_data); }; } \ No newline at end of file diff --git a/lua-api/lib/include/ScriptState.hpp b/lua-api/lib/include/ScriptState.hpp index 72be97ac..0af9fc29 100644 --- a/lua-api/lib/include/ScriptState.hpp +++ b/lua-api/lib/include/ScriptState.hpp @@ -52,6 +52,7 @@ class ScriptState { void on_frame(); void on_draw_ui(); void on_script_reset(); + void dispatch_event(std::string_view event_name, std::string_view event_data); auto& context() { return m_context; diff --git a/lua-api/lib/src/ScriptContext.cpp b/lua-api/lib/src/ScriptContext.cpp index 6bf39850..23a2c4eb 100644 --- a/lua-api/lib/src/ScriptContext.cpp +++ b/lua-api/lib/src/ScriptContext.cpp @@ -174,6 +174,10 @@ void ScriptContext::setup_callback_bindings() { "on_script_reset", [this](sol::function fn) { std::scoped_lock _{ m_mtx }; m_on_script_reset_callbacks.push_back(fn); + }, + "on_lua_event", [this](sol::function fn) { + std::scoped_lock _{ m_mtx }; + m_on_lua_event_callbacks.push_back(fn); } ); } @@ -1102,4 +1106,21 @@ void ScriptContext::on_script_reset() { } }); } + +void ScriptContext::on_lua_event(std::string_view event_name, std::string_view event_data) { + g_contexts.for_each([=](auto ctx) { + std::scoped_lock _{ ctx->m_mtx }; + + const char* event_name_data = event_name.data(); + const char* event_data_data = event_data.data(); + + for (auto& fn : ctx->m_on_lua_event_callbacks) try { + ctx->handle_protected_result(fn(event_name_data, event_data_data)); + } catch (const std::exception& e) { + ScriptContext::log("Exception in on_lua_event: " + std::string(e.what())); + } catch (...) { + ScriptContext::log("Unknown exception in on_lua_event"); + } + }); +} } \ No newline at end of file diff --git a/lua-api/lib/src/ScriptState.cpp b/lua-api/lib/src/ScriptState.cpp index 4bb195bd..e7b6d642 100644 --- a/lua-api/lib/src/ScriptState.cpp +++ b/lua-api/lib/src/ScriptState.cpp @@ -187,4 +187,10 @@ void ScriptState::on_draw_ui() { m_context->draw_ui(); } } + +void ScriptState::dispatch_event(std::string_view event_name, std::string_view event_data) { + if (m_context != nullptr) { + m_context->dispatch_event(event_name, event_data); + } +} } \ No newline at end of file diff --git a/src/mods/LuaLoader.cpp b/src/mods/LuaLoader.cpp index 30ef9980..16011b1a 100644 --- a/src/mods/LuaLoader.cpp +++ b/src/mods/LuaLoader.cpp @@ -281,4 +281,14 @@ void LuaLoader::reset_scripts() { std::sort(m_known_scripts.begin(), m_known_scripts.end()); std::sort(m_loaded_scripts.begin(), m_loaded_scripts.end()); +} + +void LuaLoader::dispatch_event(std::string_view event_name, std::string_view event_data) { + std::scoped_lock _{m_access_mutex}; + + if (m_main_state == nullptr) { + return; + } + + m_main_state->dispatch_event(event_name, event_data); } \ No newline at end of file diff --git a/src/mods/LuaLoader.hpp b/src/mods/LuaLoader.hpp index ed3d5cbf..5514fe69 100644 --- a/src/mods/LuaLoader.hpp +++ b/src/mods/LuaLoader.hpp @@ -46,6 +46,7 @@ class LuaLoader : public Mod { // Resets the ScriptState and runs autorun scripts again. void reset_scripts(); + void dispatch_event(std::string_view event_name, std::string_view event_data); private: ScriptState::GarbageCollectionData make_gc_data() const { diff --git a/src/mods/PluginLoader.cpp b/src/mods/PluginLoader.cpp index 9870a80b..c2916e5c 100644 --- a/src/mods/PluginLoader.cpp +++ b/src/mods/PluginLoader.cpp @@ -110,6 +110,10 @@ int register_inline_hook(void* target, void* dst, void** original) { void unregister_inline_hook(int id) { PluginLoader::get()->remove_inline_hook(id); } + +void dispatch_lua_event(const char* event_name, const char* event_data) { + LuaLoader::get()->dispatch_event(event_name, event_data); +} } namespace uevr { @@ -188,7 +192,8 @@ UEVR_PluginFunctions g_plugin_functions { uevr::remove_callback, uevr::get_persistent_dir, uevr::register_inline_hook, - uevr::unregister_inline_hook + uevr::unregister_inline_hook, + uevr::dispatch_lua_event }; #define GET_ENGINE_WORLD_RETNULL() \