feat(lua): Expose Script Patches & Functions (#3393)
This commit is contained in:
parent
8d5d5cb73c
commit
8f980ff1ac
@ -2,11 +2,16 @@
|
|||||||
|
|
||||||
Table containing helper functions related to gta scripts.
|
Table containing helper functions related to gta scripts.
|
||||||
|
|
||||||
## Functions (3)
|
## Functions (5)
|
||||||
|
|
||||||
### `register_looped(name, func)`
|
### `register_looped(name, func)`
|
||||||
|
|
||||||
Registers a function that will be looped as a gta script.
|
Registers a function that will be looped as a gta script.
|
||||||
|
|
||||||
|
- **Parameters:**
|
||||||
|
- `name` (string): name of your new looped script
|
||||||
|
- `func` (function): function that will be executed in a forever loop.
|
||||||
|
|
||||||
**Example Usage:**
|
**Example Usage:**
|
||||||
```lua
|
```lua
|
||||||
script.register_looped("nameOfMyLoopedScript", function (script)
|
script.register_looped("nameOfMyLoopedScript", function (script)
|
||||||
@ -31,18 +36,13 @@ script.register_looped("nameOfMyLoopedScript", function (script)
|
|||||||
end)
|
end)
|
||||||
```
|
```
|
||||||
|
|
||||||
- **Parameters:**
|
|
||||||
- `name` (string): name of your new looped script
|
|
||||||
- `func` (function): function that will be executed in a forever loop.
|
|
||||||
|
|
||||||
**Example Usage:**
|
|
||||||
```lua
|
|
||||||
script.register_looped(name, func)
|
|
||||||
```
|
|
||||||
|
|
||||||
### `run_in_fiber(func)`
|
### `run_in_fiber(func)`
|
||||||
|
|
||||||
Executes a function once inside the fiber pool, you can call natives inside it and yield or sleep.
|
Executes a function once inside the fiber pool, you can call natives inside it and yield or sleep.
|
||||||
|
|
||||||
|
- **Parameters:**
|
||||||
|
- `func` (function): function that will be executed once in the fiber pool.
|
||||||
|
|
||||||
**Example Usage:**
|
**Example Usage:**
|
||||||
```lua
|
```lua
|
||||||
script.run_in_fiber(function (script)
|
script.run_in_fiber(function (script)
|
||||||
@ -67,23 +67,45 @@ script.run_in_fiber(function (script)
|
|||||||
end)
|
end)
|
||||||
```
|
```
|
||||||
|
|
||||||
- **Parameters:**
|
|
||||||
- `func` (function): function that will be executed once in the fiber pool.
|
|
||||||
|
|
||||||
**Example Usage:**
|
|
||||||
```lua
|
|
||||||
script.run_in_fiber(func)
|
|
||||||
```
|
|
||||||
|
|
||||||
### `execute_as_script(script_name, func)`
|
### `execute_as_script(script_name, func)`
|
||||||
|
|
||||||
- **Parameters:**
|
- **Parameters:**
|
||||||
- `script_name` (string): target script thread.
|
- `script_name` (string): Target script thread.
|
||||||
- `func` (function): function that will be executed once in the script thread.
|
- `func` (function): Function that will be executed once in the script thread.
|
||||||
|
|
||||||
**Example Usage:**
|
**Example Usage:**
|
||||||
```lua
|
```lua
|
||||||
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.
|
||||||
|
|
||||||
|
- **Parameters:**
|
||||||
|
- `script_name` (string): The name of the script.
|
||||||
|
- `name` (string): The name of the patch.
|
||||||
|
- `pattern` (string): 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("fm_content_xmas_truck", "Flickering Fix", "56 ? ? 4F ? ? 40 ? 5D ? ? ? 74", 0, {0x2B, 0x00, 0x00})
|
||||||
|
```
|
||||||
|
|
||||||
|
### `call_function(name, script_name, pattern, offset, _args)`
|
||||||
|
|
||||||
|
Calls a function from the specified script.
|
||||||
|
|
||||||
|
- **Parameters:**
|
||||||
|
- `name` (string): The name of the script function.
|
||||||
|
- `script_name` (string): The name of the script.
|
||||||
|
- `pattern` (string): The pattern to scan for within the script.
|
||||||
|
- `offset` (integer): The position within the pattern.
|
||||||
|
- `_args` (table): The arguments to pass to the script function.
|
||||||
|
|
||||||
|
**Example Usage:**
|
||||||
|
```lua
|
||||||
|
script.call_function("Collect Collectible", "freemode", "2D 05 33 00 00", 0, {17, 0, 1, 1, 0})
|
||||||
|
```
|
@ -4,6 +4,10 @@
|
|||||||
#include "lua/lua_manager.hpp"
|
#include "lua/lua_manager.hpp"
|
||||||
#include "script_mgr.hpp"
|
#include "script_mgr.hpp"
|
||||||
#include "gta_util.hpp"
|
#include "gta_util.hpp"
|
||||||
|
#include "script_function.hpp"
|
||||||
|
#include "lua/bindings/network.hpp"
|
||||||
|
#include "memory/pattern.hpp"
|
||||||
|
#include "services/script_patcher/script_patcher_service.hpp"
|
||||||
|
|
||||||
namespace lua::script
|
namespace lua::script
|
||||||
{
|
{
|
||||||
@ -155,19 +159,64 @@ namespace lua::script
|
|||||||
// Lua API: function
|
// Lua API: function
|
||||||
// Table: script
|
// Table: script
|
||||||
// Name: execute_as_script
|
// Name: execute_as_script
|
||||||
// Param: script_name: string: target script thread.
|
// Param: script_name: string: Target script thread.
|
||||||
// Param: func: function: function that will be executed once in the script thread.
|
// Param: func: function: Function that will be executed once in the script thread.
|
||||||
static void execute_as_script(const std::string& script_name, sol::protected_function func)
|
static void execute_as_script(const std::string& script_name, sol::protected_function func)
|
||||||
{
|
{
|
||||||
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
|
||||||
|
// Table: script
|
||||||
|
// Name: call_function
|
||||||
|
// Param: name: string: The name of the script function.
|
||||||
|
// Param: script_name: string: The name of the script.
|
||||||
|
// Param: pattern: string: The pattern to scan for within the script.
|
||||||
|
// Param offset: integer: The position within the pattern.
|
||||||
|
// Param _args: table: The arguments to pass to the script function.
|
||||||
|
// Calls a function from the specified script.
|
||||||
|
// **Example Usage:**
|
||||||
|
//```lua
|
||||||
|
//script.call_function("Collect Collectible", "freemode", "2D 05 33 00 00", 0, {17, 0, 1, 1, 0})
|
||||||
|
//```
|
||||||
|
static void call_function(const std::string& name, const std::string& script_name, const std::string& pattern, int offset, sol::table _args)
|
||||||
|
{
|
||||||
|
auto args = convert_sequence<uint64_t>(_args);
|
||||||
|
|
||||||
|
big::script_function script_function(name, rage::joaat(script_name), pattern, offset);
|
||||||
|
script_function(args);
|
||||||
|
}
|
||||||
|
|
||||||
void bind(sol::state& state)
|
void bind(sol::state& state)
|
||||||
{
|
{
|
||||||
auto ns = state["script"].get_or_create<sol::table>();
|
auto ns = state["script"].get_or_create<sol::table>();
|
||||||
ns["register_looped"] = register_looped;
|
ns["register_looped"] = register_looped;
|
||||||
ns["run_in_fiber"] = run_in_fiber;
|
ns["run_in_fiber"] = run_in_fiber;
|
||||||
ns["execute_as_script"] = execute_as_script;
|
ns["execute_as_script"] = execute_as_script;
|
||||||
|
ns["add_patch"] = add_patch;
|
||||||
|
ns["call_function"] = call_function;
|
||||||
|
|
||||||
auto usertype = state.new_usertype<script_util>("script_util");
|
auto usertype = state.new_usertype<script_util>("script_util");
|
||||||
|
|
||||||
|
@ -38,7 +38,7 @@ namespace big
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void script_function::call(rage::scrThread* thread, rage::scrProgram* program, std::initializer_list<uint64_t> args)
|
void script_function::call(rage::scrThread* thread, rage::scrProgram* program, const std::vector<uint64_t>& args)
|
||||||
{
|
{
|
||||||
auto tls_ctx = rage::tlsContext::get();
|
auto tls_ctx = rage::tlsContext::get();
|
||||||
auto stack = (uint64_t*)thread->m_stack;
|
auto stack = (uint64_t*)thread->m_stack;
|
||||||
@ -49,7 +49,7 @@ namespace big
|
|||||||
|
|
||||||
rage::scrThreadContext ctx = thread->m_context;
|
rage::scrThreadContext ctx = thread->m_context;
|
||||||
|
|
||||||
for (auto& arg : args)
|
for (const auto& arg : args)
|
||||||
stack[ctx.m_stack_pointer++] = arg;
|
stack[ctx.m_stack_pointer++] = arg;
|
||||||
|
|
||||||
stack[ctx.m_stack_pointer++] = 0;
|
stack[ctx.m_stack_pointer++] = 0;
|
||||||
@ -62,7 +62,7 @@ namespace big
|
|||||||
tls_ctx->m_is_script_thread_active = og_thread != nullptr;
|
tls_ctx->m_is_script_thread_active = og_thread != nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void script_function::call_latent(rage::scrThread* thread, rage::scrProgram* program, std::initializer_list<uint64_t> args, bool& done)
|
void script_function::call_latent(rage::scrThread* thread, rage::scrProgram* program, const std::vector<uint64_t>& args, bool& done)
|
||||||
{
|
{
|
||||||
g_fiber_pool->queue_job([this, thread, program, args, &done] {
|
g_fiber_pool->queue_job([this, thread, program, args, &done] {
|
||||||
auto stack = (uint64_t*)thread->m_stack;
|
auto stack = (uint64_t*)thread->m_stack;
|
||||||
@ -71,7 +71,7 @@ namespace big
|
|||||||
|
|
||||||
rage::scrThreadContext ctx = thread->m_context;
|
rage::scrThreadContext ctx = thread->m_context;
|
||||||
|
|
||||||
for (auto& arg : args)
|
for (const auto& arg : args)
|
||||||
stack[ctx.m_stack_pointer++] = arg;
|
stack[ctx.m_stack_pointer++] = arg;
|
||||||
|
|
||||||
stack[ctx.m_stack_pointer++] = 0;
|
stack[ctx.m_stack_pointer++] = 0;
|
||||||
@ -101,7 +101,7 @@ namespace big
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void script_function::static_call(std::initializer_list<uint64_t> args)
|
void script_function::static_call(const std::vector<uint64_t>& args)
|
||||||
{
|
{
|
||||||
populate_ip();
|
populate_ip();
|
||||||
|
|
||||||
@ -119,7 +119,7 @@ namespace big
|
|||||||
delete[] (uint8_t*)thread; // without the cast it ends up calling the destructor which leads to some pretty funny crashes
|
delete[] (uint8_t*)thread; // without the cast it ends up calling the destructor which leads to some pretty funny crashes
|
||||||
}
|
}
|
||||||
|
|
||||||
void script_function::operator()(std::initializer_list<uint64_t> args)
|
void script_function::operator()(const std::vector<uint64_t>& args)
|
||||||
{
|
{
|
||||||
populate_ip();
|
populate_ip();
|
||||||
|
|
||||||
|
@ -16,13 +16,13 @@ namespace big
|
|||||||
public:
|
public:
|
||||||
script_function(const std::string& name, const rage::joaat_t script, const std::string& pattern, int32_t offset);
|
script_function(const std::string& name, const rage::joaat_t script, const std::string& pattern, int32_t offset);
|
||||||
void populate_ip();
|
void populate_ip();
|
||||||
void call(rage::scrThread* thread, rage::scrProgram* program, std::initializer_list<uint64_t> args);
|
void call(rage::scrThread* thread, rage::scrProgram* program, const std::vector<uint64_t>& args);
|
||||||
void call_latent(rage::scrThread* thread, rage::scrProgram* program, std::initializer_list<uint64_t> args, bool& done);
|
void call_latent(rage::scrThread* thread, rage::scrProgram* program, const std::vector<uint64_t>& args, bool& done);
|
||||||
|
|
||||||
// for pure functions that do not need access to thread stack
|
// for pure functions that do not need access to thread stack
|
||||||
void static_call(std::initializer_list<uint64_t> args);
|
void static_call(const std::vector<uint64_t>& args);
|
||||||
|
|
||||||
void operator()(std::initializer_list<uint64_t> args);
|
void operator()(const std::vector<uint64_t>& args);
|
||||||
};
|
};
|
||||||
|
|
||||||
namespace scr_functions
|
namespace scr_functions
|
||||||
|
Reference in New Issue
Block a user