Lua Scripting (#1334)

Closes #83
Fixes #1309
Fixes #1287
Fixes #1129 (actually fixed now)
This commit is contained in:
maybegreat48
2023-06-06 07:40:40 +00:00
committed by GitHub
parent a8750a30fb
commit 70efa40afe
202 changed files with 156693 additions and 839 deletions

View File

@ -44,6 +44,7 @@ namespace big
STAT_EDITOR,
SETTINGS,
LUA_SCRIPTS,
CONTEXT_MENU_SETTINGS,
ESP_SETTINGS,
GTA_CACHE_SETTINGS,
@ -62,6 +63,7 @@ namespace big
const char name[48] = "";
std::function<void()> func = nullptr;
std::map<tabs, navigation_struct> sub_nav{};
rage::joaat_t hash = rage::joaat(name);
};
class gui_service final
@ -146,6 +148,7 @@ namespace big
"GUI_TAB_SETTINGS",
view::settings,
{
{tabs::LUA_SCRIPTS, {"GUI_TAB_LUA_SCRIPTS", view::lua_scripts}},
{tabs::CONTEXT_MENU_SETTINGS, {"GUI_TAB_CONTEXT_MENU", view::context_menu_settings}},
{tabs::ESP_SETTINGS, {"GUI_TAB_ESP", view::esp_settings}},
{tabs::GTA_CACHE_SETTINGS, {"GTA Cache", view::gta_cache}},

View File

@ -22,22 +22,22 @@ namespace big
this->notifications.emplace(std::hash<std::string>{}(n.message + n.title), n);
}
void notification_service::push(std::string title, std::string message)
void notification_service::push(const std::string& title, const std::string& message)
{
this->push({NotificationType::INFO, title, message, std::chrono::system_clock::now(), 5000.f, 1.f});
}
void notification_service::push_warning(std::string title, std::string message)
void notification_service::push_warning(const std::string& title, const std::string& message)
{
this->push({NotificationType::WARNING, title, message, std::chrono::system_clock::now(), 7000.f, 1.f});
}
void notification_service::push_error(std::string title, std::string message)
void notification_service::push_error(const std::string& title, const std::string& message)
{
this->push({NotificationType::DANGER, title, message, std::chrono::system_clock::now(), 7000.f, 1.f});
}
void notification_service::push_success(std::string title, std::string message)
void notification_service::push_success(const std::string& title, const std::string& message)
{
this->push({NotificationType::SUCCESS, title, message, std::chrono::system_clock::now(), 7000.f, 1.f});
}

View File

@ -28,10 +28,10 @@ namespace big
virtual ~notification_service();
void push(notification);
void push(std::string, std::string);
void push_warning(std::string, std::string);
void push_error(std::string, std::string);
void push_success(std::string, std::string);
void push(const std::string&, const std::string&);
void push_warning(const std::string&, const std::string&);
void push_error(const std::string&, const std::string&);
void push_success(const std::string&, const std::string&);
std::vector<notification> get();
std::map<NotificationType, ImVec4> notification_colors = {

View File

@ -83,6 +83,8 @@ namespace big
std::optional<std::uint32_t> time_difference;
std::uint32_t num_time_syncs_sent = 9999;
bool block_explosions = false;
protected:
bool equals(const CNetGamePlayer* net_game_player) const;

View File

@ -8,7 +8,8 @@
namespace big
{
translation_service::translation_service() :
m_url("https://cdn.jsdelivr.net/gh/YimMenu/Translations@master")
m_url("https://raw.githubusercontent.com/YimMenu/Translations/master"),
m_fallback_url("https://cdn.jsdelivr.net/gh/YimMenu/Translations@master")
{
}
@ -39,7 +40,6 @@ namespace big
m_local_index.version = m_remote_index.version;
}
load_translations();
return;
}
@ -151,7 +151,7 @@ namespace big
{
if (auto it = m_remote_index.translations.find(pack_id.data()); it != m_remote_index.translations.end())
{
cpr::Response response = cpr::Get(cpr::Url{m_url + "/" + it->second.file});
cpr::Response response = download_file("/" + it->second.file);
if (response.status_code == 200)
{
@ -170,7 +170,7 @@ namespace big
bool translation_service::download_index()
{
cpr::Response response = cpr::Get(cpr::Url{m_url + "/index.json"});
cpr::Response response = download_file("/index.json");
if (response.status_code == 200)
{
@ -210,4 +210,14 @@ namespace big
m_remote_index.default_lang = m_local_index.fallback_default_language;
m_remote_index.translations = m_local_index.fallback_languages;
}
cpr::Response translation_service::download_file(const std::string& filename)
{
cpr::Response response = cpr::Get(cpr::Url{m_url + filename});
if (response.status_code != 200)
response = cpr::Get(cpr::Url{m_fallback_url + filename});
return response;
}
}

View File

@ -4,6 +4,8 @@
#include "local_index.hpp"
#include "remote_index.hpp"
#include <cpr/response.h>
namespace big
{
using translation_map = std::unordered_map<rage::joaat_t, std::string>;
@ -47,9 +49,12 @@ namespace big
* @brief Attempts to load the remote from the local index fallback
*/
void use_fallback_remote();
cpr::Response download_file(const std::string& filename);
private:
const std::string m_url;
const std::string m_fallback_url;
std::unique_ptr<folder> m_translation_directory;
local_index m_local_index;
remote_index m_remote_index;

View File

@ -0,0 +1,134 @@
#include "tunables_service.hpp"
#include "memory/module.hpp"
#include "natives.hpp"
#include "pointers.hpp"
#include "script.hpp"
#include "services/script_patcher/script_patcher_service.hpp"
#include "thread_pool.hpp"
#include "util/scripts.hpp"
namespace big
{
tunables_service::tunables_service() :
m_cache_file(g_file_manager->get_project_file("./cache/tunables.bin"), 1)
{
m_cache_file.load();
if (m_cache_file.up_to_date(memory::module("GTA5.exe").size()))
{
LOG(INFO) << "Loading tunables from cache";
m_loading = true;
g_thread_pool->push([this] {
while (!g_pointers->m_gta.m_script_globals[1])
{
if (!m_loading)
return;
std::this_thread::yield();
}
load();
});
}
g_tunables_service = this;
}
tunables_service::~tunables_service()
{
m_loading = false;
g_tunables_service = nullptr;
}
void tunables_service::run_script()
{
while (true)
{
script::get_current()->yield();
if (m_initialized || m_loading)
return;
if (!m_script_started && SCRIPT::GET_NUMBER_OF_THREADS_RUNNING_THE_SCRIPT_WITH_THIS_HASH(RAGE_JOAAT("tuneables_processing")) > 0)
continue;
if (!m_script_started)
{
SCRIPT::REQUEST_SCRIPT_WITH_NAME_HASH(RAGE_JOAAT("tuneables_processing"));
if (SCRIPT::HAS_SCRIPT_WITH_NAME_HASH_LOADED(RAGE_JOAAT("tuneables_processing")))
{
std::uint64_t args[] = {6, 27, 1}; // TODO: check args
int id = SYSTEM::START_NEW_SCRIPT_WITH_NAME_HASH_AND_ARGS(RAGE_JOAAT("tuneables_processing"), (Any*)args, sizeof(args) / 8, 1424);
if (!id)
{
LOG(FATAL) << "Failed to start tuneables_processing. Cannot cache tunables";
return;
}
SCRIPT::SET_SCRIPT_WITH_NAME_HASH_AS_NO_LONGER_NEEDED(RAGE_JOAAT("tuneables_processing"));
m_script_started = true;
g_script_patcher_service->add_patch({RAGE_JOAAT("tuneables_processing"), "2E ? ? 55 ? ? 38 06", 0, std::vector<uint8_t>(17, 0x0), &m_script_started}); // bool tunables registration hack
if (auto program = gta_util::find_script_program(RAGE_JOAAT("tuneables_processing")))
g_script_patcher_service->on_script_load(program);
}
}
else
{
if (SCRIPT::GET_NUMBER_OF_THREADS_RUNNING_THE_SCRIPT_WITH_THIS_HASH(RAGE_JOAAT("tuneables_processing")) == 0)
{
m_script_started = false;
m_initialized = true;
LOG(INFO) << "Saving " << m_tunables.size() << " tunables to cache";
g_script_patcher_service->update();
save();
}
}
}
}
void tunables_service::save()
{
auto data_size = sizeof(std::uint32_t) + sizeof(tunable_save_struct) * m_tunables.size();
auto data = std::make_unique<std::uint8_t[]>(data_size);
auto data_ptr = data.get();
*(std::uint32_t*)data_ptr = m_tunables.size();
data_ptr += sizeof(std::uint32_t);
for (auto& [hash, ptr] : m_tunables)
{
auto save_struct = (tunable_save_struct*)data_ptr;
save_struct->hash = hash;
save_struct->offset = ((std::int64_t*)ptr) - g_pointers->m_gta.m_script_globals[1];
data_ptr += sizeof(tunable_save_struct);
}
m_cache_file.set_header_version(memory::module("GTA5.exe").size());
m_cache_file.set_data(std::move(data), data_size);
m_cache_file.write();
}
void tunables_service::load()
{
auto data = m_cache_file.data();
auto num_tunables = *(std::uint32_t*)data;
data += sizeof(std::uint32_t);
for (int i = 0; i < num_tunables; i++)
{
auto save_struct = (tunable_save_struct*)data;
m_tunables.emplace(save_struct->hash, (void*)(g_pointers->m_gta.m_script_globals[1] + save_struct->offset));
data += sizeof(tunable_save_struct);
}
m_initialized = true;
m_loading = false;
}
}

View File

@ -0,0 +1,93 @@
#pragma once
#include "fiber_pool.hpp"
#include "script.hpp"
#include "services/gta_data/cache_file.hpp"
namespace big
{
#pragma pack(push, 1)
struct tunable_save_struct
{
rage::joaat_t hash;
std::uint32_t offset;
};
#pragma pack(pop)
class tunables_service
{
public:
tunables_service();
~tunables_service();
void run_script();
inline bool caching_tunables()
{
return m_script_started;
}
inline bool initialized()
{
return m_initialized;
}
inline void register_tunable(rage::joaat_t hash, void* pointer)
{
m_tunables.emplace(hash, pointer);
}
template<typename T>
inline std::enable_if_t<std::is_pointer_v<T>, T> get_tunable(rage::joaat_t hash)
{
if (auto it = m_tunables.find(hash); it != m_tunables.end())
return reinterpret_cast<T>(it->second);
return nullptr;
}
// wrapper around get_tunable(), may not set the tunable immediately if the service isn't initialized yet
template<typename T>
inline void set_tunable(rage::joaat_t hash, T value)
{
if (initialized())
{
if (auto tunable = get_tunable<T*>(hash))
{
*tunable = value;
LOG(INFO) << "Imm set";
}
else
{
LOG(INFO) << "Not found";
}
}
else
{
g_fiber_pool->queue_job([this, hash, value] {
while (!initialized())
script::get_current()->yield();
if (auto tunable = get_tunable<T*>(hash))
{
*tunable = value;
LOG(INFO) << "Delay set";
}
});
}
}
private:
bool m_initialized = false;
bool m_loading = false;
bool m_script_started = false;
cache_file m_cache_file;
std::unordered_map<rage::joaat_t, void*> m_tunables{};
void save();
void load();
};
inline tunables_service* g_tunables_service;
}