Locals editor (#1211)
This commit is contained in:
126
src/services/locals/locals_service.cpp
Normal file
126
src/services/locals/locals_service.cpp
Normal file
@ -0,0 +1,126 @@
|
||||
#include "locals_service.hpp"
|
||||
|
||||
#include "core/data/all_script_names.hpp"
|
||||
#include "natives.hpp"
|
||||
#include "pointers.hpp"
|
||||
#include "fiber_pool.hpp"
|
||||
|
||||
namespace big
|
||||
{
|
||||
|
||||
bool locals_service::is_script_thread_running(GtaThread* thread)
|
||||
{
|
||||
if (thread)
|
||||
{
|
||||
return thread->m_context.m_state == rage::eThreadState::running || thread->m_context.m_state == rage::eThreadState::idle;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool locals_service::does_script_exist(std::string script_name)
|
||||
{
|
||||
for (auto s : all_script_names)
|
||||
if (script_name == s)
|
||||
return true;
|
||||
bool script_exists = false;
|
||||
g_fiber_pool->queue_job([&] {script_exists = SCRIPT::DOES_SCRIPT_EXIST(script_name.data());});
|
||||
return script_exists;
|
||||
}
|
||||
|
||||
std::filesystem::path locals_service::get_path()
|
||||
{
|
||||
return g_file_manager->get_project_file("locals.json").get_path();
|
||||
}
|
||||
|
||||
bool locals_service::load()
|
||||
{
|
||||
std::ifstream file(locals_service::get_path());
|
||||
if (!file.is_open())
|
||||
return false;
|
||||
|
||||
try
|
||||
{
|
||||
nlohmann::json j;
|
||||
file >> j;
|
||||
m_locals.clear();
|
||||
for (const auto& l : j.items())
|
||||
{
|
||||
if (!l.key().empty())
|
||||
{
|
||||
local new_local{"", "", 0, 0, 0, 0};
|
||||
new_local.m_base_address = j[l.key()]["base_address"];
|
||||
std::string script_name = j[l.key()]["script_thread_name"];
|
||||
strcpy(new_local.m_script_thread_name, script_name.data());
|
||||
new_local.m_freeze = j[l.key()]["freeze"];
|
||||
std::string name = j[l.key()]["name"];
|
||||
strcpy(new_local.m_name, name.data());
|
||||
new_local.m_value = j[l.key()]["value"];
|
||||
if (!j[l.key()]["offsets"].is_null())
|
||||
{
|
||||
for (const auto& offset : j[l.key()]["offsets"].items())
|
||||
{
|
||||
if (!offset.key().empty())
|
||||
{
|
||||
local_offset new_offset{0, 0};
|
||||
new_offset.m_offset = j[l.key()]["offsets"][offset.key()]["offset"];
|
||||
if (!j[l.key()]["offsets"][offset.key()]["size"].is_null())
|
||||
new_offset.m_size = j[l.key()]["offsets"][offset.key()]["size"];
|
||||
new_local.m_offsets.push_back(new_offset);
|
||||
}
|
||||
}
|
||||
}
|
||||
new_local.fetch_local_pointer();
|
||||
m_locals.push_back(new_local);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (const std::exception&)
|
||||
{
|
||||
LOG(WARNING) << "Failure to parse locals.json, aborting...";
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void locals_service::save()
|
||||
{
|
||||
std::map<std::string, local> locals_with_names;
|
||||
for (auto& l : m_locals)
|
||||
{
|
||||
locals_with_names.insert(std::pair<std::string, local>(std::string(l.m_name).empty() ? std::string(l.m_script_thread_name + std::string("_") + std::to_string(l.m_base_address)) : l.m_name, l));
|
||||
}
|
||||
|
||||
nlohmann::json j;
|
||||
for (auto& l : locals_with_names)
|
||||
{
|
||||
j[l.first]["script_thread_name"] = l.second.m_script_thread_name;
|
||||
j[l.first]["base_address"] = l.second.m_base_address;
|
||||
j[l.first]["freeze"] = l.second.m_freeze;
|
||||
j[l.first]["name"] = l.second.m_name;
|
||||
j[l.first]["value"] = l.second.m_value;
|
||||
|
||||
for (int i = 0; i < l.second.m_offsets.size(); i++)
|
||||
{
|
||||
j[l.first]["offsets"][std::to_string(i)]["offset"] = l.second.m_offsets[i].m_offset;
|
||||
if (l.second.m_offsets[i].m_size > 0)
|
||||
j[l.first]["offsets"][std::to_string(i)]["size"] = l.second.m_offsets[i].m_size;
|
||||
};
|
||||
}
|
||||
|
||||
std::ofstream file(locals_service::get_path(), std::ios::out | std::ios::trunc);
|
||||
|
||||
try
|
||||
{
|
||||
file << j.dump(4);
|
||||
|
||||
file.close();
|
||||
}
|
||||
catch (const std::exception&)
|
||||
{
|
||||
LOG(WARNING) << "Failed to write to locals.json";
|
||||
}
|
||||
}
|
||||
|
||||
};
|
104
src/services/locals/locals_service.hpp
Normal file
104
src/services/locals/locals_service.hpp
Normal file
@ -0,0 +1,104 @@
|
||||
#pragma once
|
||||
|
||||
#include "file_manager.hpp"
|
||||
#include "file_manager/file.hpp"
|
||||
#include "gta/script_thread.hpp"
|
||||
#include "gta_util.hpp"
|
||||
#include "script_local.hpp"
|
||||
|
||||
namespace big
|
||||
{
|
||||
|
||||
struct local_offset
|
||||
{
|
||||
local_offset(int offset, int size = 0)
|
||||
{
|
||||
m_offset = offset;
|
||||
|
||||
if (size)
|
||||
m_size = size;
|
||||
}
|
||||
|
||||
int m_offset = 0;
|
||||
int m_size = 0;
|
||||
};
|
||||
|
||||
|
||||
struct local
|
||||
{
|
||||
GtaThread* m_script_thread;
|
||||
char m_script_thread_name[200];
|
||||
int m_base_address;
|
||||
bool m_freeze = false;
|
||||
char m_name[200];
|
||||
std::vector<local_offset> m_offsets;
|
||||
int m_value;
|
||||
int m_freeze_value;
|
||||
int* m_internal_address;
|
||||
|
||||
local(const char* script_thread_name, const char* name, const int base_address, const bool freeze, const int (*offsets)[2], int offset_count)
|
||||
{
|
||||
m_internal_id = ++m_instance_count;
|
||||
|
||||
strcpy(m_script_thread_name, script_thread_name);
|
||||
m_base_address = base_address;
|
||||
m_freeze = freeze;
|
||||
strcpy(m_name, name);
|
||||
m_value = 0;
|
||||
|
||||
for (int i = 0; i < offset_count; i++)
|
||||
m_offsets.push_back(local_offset(offsets[i][0], offsets[i][1]));
|
||||
|
||||
fetch_local_pointer();
|
||||
}
|
||||
|
||||
int get_id() const
|
||||
{
|
||||
return m_internal_id;
|
||||
}
|
||||
|
||||
int* fetch_local_pointer()
|
||||
{
|
||||
m_script_thread = gta_util::find_script_thread(rage::joaat(m_script_thread_name));
|
||||
|
||||
if (m_script_thread)
|
||||
{
|
||||
script_local actual_local = script_local(m_script_thread, m_base_address);
|
||||
|
||||
for (auto offset : m_offsets)
|
||||
{
|
||||
if (offset.m_size > 0)
|
||||
actual_local = actual_local.at(offset.m_offset, offset.m_size);
|
||||
else
|
||||
actual_local = actual_local.at(offset.m_offset);
|
||||
}
|
||||
|
||||
m_internal_address = actual_local.as<int*>();
|
||||
|
||||
return m_internal_address;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
private:
|
||||
inline static int m_instance_count;
|
||||
int m_internal_id;
|
||||
};
|
||||
|
||||
|
||||
class locals_service
|
||||
{
|
||||
public:
|
||||
std::filesystem::path get_path();
|
||||
bool load();
|
||||
void save();
|
||||
|
||||
static bool does_script_exist(std::string script);
|
||||
static bool is_script_thread_running(GtaThread* thread);
|
||||
|
||||
std::vector<local> m_locals;
|
||||
bool m_running = false;
|
||||
};
|
||||
|
||||
inline locals_service g_locals_service{};
|
||||
}
|
Reference in New Issue
Block a user