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
This commit is contained in:
Arthur 2024-08-22 20:52:02 +03:00 committed by GitHub
parent 88aa4d317e
commit 61ff817f11
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
9 changed files with 142 additions and 46 deletions

View File

@ -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()
```

View File

@ -102,26 +102,6 @@ script.is_active(script_name)
script.execute_as_script(script_name, func) 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)` ### `start_launcher_script(script_name)`
Tries to start a launcher script. Needs to be called in the fiber pool or a loop. Tries to start a launcher script. Needs to be called in the fiber pool or a loop.

View File

@ -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<uint8_t>(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<scr_patch>(*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>("scr_patch", sol::constructors<scr_patch(const std::string&, const std::string&, const std::string&, const int, sol::table, sol::this_state)>());
scr_patch_ut["enable_patch"] = &scr_patch::enable;
scr_patch_ut["disable_patch"] = &scr_patch::disable;
}
}

View File

@ -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);
}

View File

@ -3,9 +3,7 @@
#include "lua/lua_manager.hpp" #include "lua/lua_manager.hpp"
#include "gta_util.hpp" #include "gta_util.hpp"
#include "lua/bindings/network.hpp"
#include "memory/pattern.hpp" #include "memory/pattern.hpp"
#include "services/script_patcher/script_patcher_service.hpp"
#include "util/scripts.hpp" #include "util/scripts.hpp"
namespace lua::script namespace lua::script
@ -182,28 +180,6 @@ namespace lua::script
big::gta_util::execute_as_script(rage::joaat(script_name), func); 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<uint8_t>(_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 // Lua API: function
// Table: script // Table: script
// Name: start_launcher_script // Name: start_launcher_script
@ -227,7 +203,6 @@ namespace lua::script
ns["run_in_fiber"] = run_in_fiber; ns["run_in_fiber"] = run_in_fiber;
ns["is_active"] = is_active; ns["is_active"] = is_active;
ns["execute_as_script"] = execute_as_script; ns["execute_as_script"] = execute_as_script;
ns["add_patch"] = add_patch;
ns["start_launcher_script"] = start_launcher_script; ns["start_launcher_script"] = start_launcher_script;
auto usertype = state.new_usertype<script_util>("script_util"); auto usertype = state.new_usertype<script_util>("script_util");

View File

@ -14,6 +14,7 @@
#include "bindings/network.hpp" #include "bindings/network.hpp"
#include "bindings/script.hpp" #include "bindings/script.hpp"
#include "bindings/scr_function.hpp" #include "bindings/scr_function.hpp"
#include "bindings/scr_patch.hpp"
#include "bindings/self.hpp" #include "bindings/self.hpp"
#include "bindings/stats.hpp" #include "bindings/stats.hpp"
#include "bindings/tunables.hpp" #include "bindings/tunables.hpp"
@ -300,6 +301,7 @@ namespace big
lua::globals::bind(m_state); lua::globals::bind(m_state);
lua::script::bind(m_state); lua::script::bind(m_state);
lua::scr_function::bind(m_state); lua::scr_function::bind(m_state);
lua::scr_patch::bind(m_state);
lua::native::bind(m_state); lua::native::bind(m_state);
lua::memory::bind(m_state); lua::memory::bind(m_state);
lua::gui::bind(m_state); lua::gui::bind(m_state);

View File

@ -4,6 +4,7 @@
#include "core/data/menu_event.hpp" #include "core/data/menu_event.hpp"
#include "lua/bindings/runtime_func_t.hpp" #include "lua/bindings/runtime_func_t.hpp"
#include "lua/bindings/type_info_t.hpp" #include "lua/bindings/type_info_t.hpp"
#include "lua/bindings/scr_patch.hpp"
#include "lua_patch.hpp" #include "lua_patch.hpp"
#include "services/gui/gui_service.hpp" #include "services/gui/gui_service.hpp"
@ -28,6 +29,7 @@ namespace big
public: public:
std::vector<std::unique_ptr<script>> m_registered_scripts; std::vector<std::unique_ptr<script>> m_registered_scripts;
std::vector<std::unique_ptr<lua_patch>> m_registered_patches; std::vector<std::unique_ptr<lua_patch>> m_registered_patches;
std::vector<std::unique_ptr<lua::scr_patch::scr_patch>> m_registered_script_patches;
std::vector<big::tabs> m_owned_tabs; std::vector<big::tabs> m_owned_tabs;

View File

@ -14,7 +14,6 @@ namespace big
script_data* get_data_for_script(rage::joaat_t script); script_data* get_data_for_script(rage::joaat_t script);
bool does_script_have_patches(rage::joaat_t script); bool does_script_have_patches(rage::joaat_t script);
void create_data_for_script(rage::scrProgram* program); void create_data_for_script(rage::scrProgram* program);
void update_all_patches_for_script(rage::joaat_t script);
public: public:
script_patcher_service(); script_patcher_service();
@ -23,6 +22,7 @@ namespace big
void add_patch(script_patch&& patch); void add_patch(script_patch&& patch);
void on_script_load(rage::scrProgram* program); void on_script_load(rage::scrProgram* program);
uint8_t** get_script_bytecode(rage::joaat_t script); uint8_t** get_script_bytecode(rage::joaat_t script);
void update_all_patches_for_script(rage::joaat_t script);
void update(); void update();
}; };

View File

@ -75,6 +75,10 @@ namespace big
"VIEW_LUA_SCRIPTS_MEMORY_PATCHES_REGISTERED"_T, "VIEW_LUA_SCRIPTS_MEMORY_PATCHES_REGISTERED"_T,
selected_module.lock()->m_registered_patches.size()) selected_module.lock()->m_registered_patches.size())
.c_str()); .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( ImGui::Text(
std::format("{}: {}", "VIEW_LUA_SCRIPTS_GUI_TABS_REGISTERED"_T, selected_module.lock()->m_gui.size()).c_str()); std::format("{}: {}", "VIEW_LUA_SCRIPTS_GUI_TABS_REGISTERED"_T, selected_module.lock()->m_gui.size()).c_str());