From 0dd43e95b850460247385e11ad840e1202ebca56 Mon Sep 17 00:00:00 2001 From: Arthur <121949966+ShinyWasabi@users.noreply.github.com> Date: Thu, 22 Aug 2024 20:52:02 +0300 Subject: [PATCH] Redesign Script Patches for Lua (#3612) * Refactor Script Patches for Lua * Use update_all_patches_for_script instead of update and store script's joaat instead of its string --- docs/lua/classes/scr_patch.md | 41 ++++++++++++++ docs/lua/tables/script.md | 20 ------- src/lua/bindings/scr_patch.cpp | 53 +++++++++++++++++++ src/lua/bindings/scr_patch.hpp | 39 ++++++++++++++ src/lua/bindings/script.cpp | 25 --------- src/lua/lua_module.cpp | 2 + src/lua/lua_module.hpp | 2 + .../script_patcher/script_patcher_service.hpp | 2 +- src/views/settings/view_lua_scripts.cpp | 4 ++ 9 files changed, 142 insertions(+), 46 deletions(-) create mode 100644 docs/lua/classes/scr_patch.md create mode 100644 src/lua/bindings/scr_patch.cpp create mode 100644 src/lua/bindings/scr_patch.hpp diff --git a/docs/lua/classes/scr_patch.md b/docs/lua/classes/scr_patch.md new file mode 100644 index 00000000..75ca7830 --- /dev/null +++ b/docs/lua/classes/scr_patch.md @@ -0,0 +1,41 @@ +# Class: scr_patch + +Class for patching GTA script functions. + +## Constructors (1) + +### `new(script_name, patch_name, pattern, offset, patch_)` + +Adds a patch for the specified script. + +- **Parameters:** + - `script_name` (string): The name of the script. + - `patch_name` (string): The name of the patch. + - `pattern` (string): The pattern to scan for within the script. + - `offset` (integer): The position within the pattern. + - `patch_` (table): The bytes to be written into the script's bytecode. + +**Example Usage:** +```lua +my_patch = scr_patch:new(script_name, patch_name, pattern, offset, patch_) +``` + +## Functions (2) + +### `enable()` + +Enables the script patch for the current instance. When a new instance is created, it will be enabled by default. + +**Example Usage:** +```lua +scr_patch:enable() +``` + +### `disable()` + +Disables the script patch for the current instance. + +**Example Usage:** +```lua +scr_patch:disable() +``` \ No newline at end of file diff --git a/docs/lua/tables/script.md b/docs/lua/tables/script.md index be26a423..0e067648 100644 --- a/docs/lua/tables/script.md +++ b/docs/lua/tables/script.md @@ -102,26 +102,6 @@ script.is_active(script_name) script.execute_as_script(script_name, func) ``` -### `add_patch(script_name, name, pattern, offset, _patch)` - -Adds a patch for the specified script. -**Example Usage:** -```lua -script.add_patch("fm_content_xmas_truck", "Flickering Fix", "56 ? ? 4F ? ? 40 ? 5D ? ? ? 74", 0, {0x2B, 0x00, 0x00}) -``` - -- **Parameters:** - - `script_name` (string): The name of the script. - - `name` (string): The name of the patch. - - `pattern` (string): The pattern to scan for within the script. - - `offset` (integer): The position within the pattern. - - `_patch` (table): The bytes to be written into the script's bytecode. - -**Example Usage:** -```lua -script.add_patch(script_name, name, pattern, offset, _patch) -``` - ### `start_launcher_script(script_name)` Tries to start a launcher script. Needs to be called in the fiber pool or a loop. diff --git a/src/lua/bindings/scr_patch.cpp b/src/lua/bindings/scr_patch.cpp new file mode 100644 index 00000000..1e27649b --- /dev/null +++ b/src/lua/bindings/scr_patch.cpp @@ -0,0 +1,53 @@ +#include "scr_patch.hpp" + +#include "gta_util.hpp" +#include "lua/lua_module.hpp" +#include "lua/bindings/network.hpp" // For convert_sequence +#include "services/script_patcher/script_patcher_service.hpp" + +namespace lua::scr_patch +{ + scr_patch::scr_patch(const std::string& script_name, const std::string& patch_name, const std::string& pattern, const int offset, sol::table patch_, sol::this_state state) : + m_script(rage::joaat(script_name)), + m_patch_name(patch_name), + m_pattern(pattern), + m_offset(offset), + m_patch(patch_), + m_enable(true) + { + auto patch = convert_sequence(m_patch); + + big::g_script_patcher_service->add_patch({m_script, m_patch_name, ::memory::pattern(m_pattern), m_offset, patch, &m_enable}); + if (auto program = big::gta_util::find_script_program(m_script)) + big::g_script_patcher_service->on_script_load(program); + + big::lua_module* module = sol::state_view(state)["!this"]; + module->m_registered_script_patches.push_back(std::make_unique(*this)); + } + + void scr_patch::enable() + { + if (!m_enable) + { + m_enable = true; + big::g_script_patcher_service->update_all_patches_for_script(m_script); + } + } + + void scr_patch::disable() + { + if (m_enable) + { + m_enable = false; + big::g_script_patcher_service->update_all_patches_for_script(m_script); + } + } + + void bind(sol::state& state) + { + auto scr_patch_ut = state.new_usertype("scr_patch", sol::constructors()); + + scr_patch_ut["enable_patch"] = &scr_patch::enable; + scr_patch_ut["disable_patch"] = &scr_patch::disable; + } +} \ No newline at end of file diff --git a/src/lua/bindings/scr_patch.hpp b/src/lua/bindings/scr_patch.hpp new file mode 100644 index 00000000..2e509366 --- /dev/null +++ b/src/lua/bindings/scr_patch.hpp @@ -0,0 +1,39 @@ +#pragma once + +namespace lua::scr_patch +{ + struct scr_patch + { + rage::joaat_t m_script; + std::string m_patch_name; + std::string m_pattern; + int m_offset; + sol::table m_patch; + bool m_enable; + + public: + // Lua API: Constructor + // Class: scr_patch + // Param: script_name: string: The name of the script. + // Param: patch_name: string: The name of the patch. + // Param: pattern: string: The pattern to scan for within the script. + // Param: offset: integer: The position within the pattern. + // Param: patch_: table: The bytes to be written into the script's bytecode. + // Adds a patch for the specified script. + explicit scr_patch(const std::string& script_name, const std::string& patch_name, const std::string& pattern, const int offset, sol::table patch_, sol::this_state state); + + // Lua API: Function + // Class: scr_patch + // Name: enable + // Enables the script patch for the current instance. When a new instance is created, it will be enabled by default. + void enable(); + + // Lua API: Function + // Class: scr_patch + // Name: disable + // Disables the script patch for the current instance. + void disable(); + }; + + void bind(sol::state& state); +} \ No newline at end of file diff --git a/src/lua/bindings/script.cpp b/src/lua/bindings/script.cpp index 80ebfa2e..5ad5b480 100644 --- a/src/lua/bindings/script.cpp +++ b/src/lua/bindings/script.cpp @@ -3,9 +3,7 @@ #include "lua/lua_manager.hpp" #include "gta_util.hpp" -#include "lua/bindings/network.hpp" #include "memory/pattern.hpp" -#include "services/script_patcher/script_patcher_service.hpp" #include "util/scripts.hpp" namespace lua::script @@ -182,28 +180,6 @@ namespace lua::script big::gta_util::execute_as_script(rage::joaat(script_name), func); } - // Lua API: function - // Table: script - // Name: add_patch - // Param: script_name: string: The name of the script. - // Param: name: string: The name of the patch. - // Param: pattern: string: The pattern to scan for within the script. - // Param: offset: integer: The position within the pattern. - // Param: _patch: table: The bytes to be written into the script's bytecode. - // Adds a patch for the specified script. - // **Example Usage:** - // ```lua - // script.add_patch("fm_content_xmas_truck", "Flickering Fix", "56 ? ? 4F ? ? 40 ? 5D ? ? ? 74", 0, {0x2B, 0x00, 0x00}) - // ``` - static void add_patch(const std::string& script_name, const std::string& name, const std::string& pattern, int offset, sol::table _patch) - { - auto patch = convert_sequence(_patch); - - big::g_script_patcher_service->add_patch({rage::joaat(script_name), name, ::memory::pattern(pattern), offset, patch, nullptr}); // TO-DO: Add toggle feature? - if (auto program = big::gta_util::find_script_program(rage::joaat(script_name))) - big::g_script_patcher_service->on_script_load(program); - } - // Lua API: function // Table: script // Name: start_launcher_script @@ -227,7 +203,6 @@ namespace lua::script ns["run_in_fiber"] = run_in_fiber; ns["is_active"] = is_active; ns["execute_as_script"] = execute_as_script; - ns["add_patch"] = add_patch; ns["start_launcher_script"] = start_launcher_script; auto usertype = state.new_usertype("script_util"); diff --git a/src/lua/lua_module.cpp b/src/lua/lua_module.cpp index 8cc0cd47..2e0a7c43 100644 --- a/src/lua/lua_module.cpp +++ b/src/lua/lua_module.cpp @@ -14,6 +14,7 @@ #include "bindings/network.hpp" #include "bindings/script.hpp" #include "bindings/scr_function.hpp" +#include "bindings/scr_patch.hpp" #include "bindings/self.hpp" #include "bindings/stats.hpp" #include "bindings/tunables.hpp" @@ -300,6 +301,7 @@ namespace big lua::globals::bind(m_state); lua::script::bind(m_state); lua::scr_function::bind(m_state); + lua::scr_patch::bind(m_state); lua::native::bind(m_state); lua::memory::bind(m_state); lua::gui::bind(m_state); diff --git a/src/lua/lua_module.hpp b/src/lua/lua_module.hpp index 099b5ab7..177a5f43 100644 --- a/src/lua/lua_module.hpp +++ b/src/lua/lua_module.hpp @@ -4,6 +4,7 @@ #include "core/data/menu_event.hpp" #include "lua/bindings/runtime_func_t.hpp" #include "lua/bindings/type_info_t.hpp" +#include "lua/bindings/scr_patch.hpp" #include "lua_patch.hpp" #include "services/gui/gui_service.hpp" @@ -28,6 +29,7 @@ namespace big public: std::vector> m_registered_scripts; std::vector> m_registered_patches; + std::vector> m_registered_script_patches; std::vector m_owned_tabs; diff --git a/src/services/script_patcher/script_patcher_service.hpp b/src/services/script_patcher/script_patcher_service.hpp index dc595cb4..4b29cd2a 100644 --- a/src/services/script_patcher/script_patcher_service.hpp +++ b/src/services/script_patcher/script_patcher_service.hpp @@ -14,7 +14,6 @@ namespace big script_data* get_data_for_script(rage::joaat_t script); bool does_script_have_patches(rage::joaat_t script); void create_data_for_script(rage::scrProgram* program); - void update_all_patches_for_script(rage::joaat_t script); public: script_patcher_service(); @@ -23,6 +22,7 @@ namespace big void add_patch(script_patch&& patch); void on_script_load(rage::scrProgram* program); uint8_t** get_script_bytecode(rage::joaat_t script); + void update_all_patches_for_script(rage::joaat_t script); void update(); }; diff --git a/src/views/settings/view_lua_scripts.cpp b/src/views/settings/view_lua_scripts.cpp index e7a5d79e..70b4fb12 100644 --- a/src/views/settings/view_lua_scripts.cpp +++ b/src/views/settings/view_lua_scripts.cpp @@ -75,6 +75,10 @@ namespace big "VIEW_LUA_SCRIPTS_MEMORY_PATCHES_REGISTERED"_T, selected_module.lock()->m_registered_patches.size()) .c_str()); + ImGui::Text(std::format("{}: {}", + "VIEW_LUA_SCRIPTS_SCRIPT_PATCHES_REGISTERED"_T, + selected_module.lock()->m_registered_script_patches.size()) + .c_str()); ImGui::Text( std::format("{}: {}", "VIEW_LUA_SCRIPTS_GUI_TABS_REGISTERED"_T, selected_module.lock()->m_gui.size()).c_str());