Clone Debug Globals into Debug Locals (#2419)
* Copied code from Debug Globals to Debug Locals. Redesigned components::input_text to return the InputText result, and add an overloaded method to take a std::string. Fixed Debug Globals having static text and not using components::input_text to prevent sending the input to the game. Fixed view_debug_threads::thread_states not properly ending its string causing ImGui to read more than it should from memory. Made Debug Globals cap the input index to UINT32, as the user could potentially overflow the get_ptr function and cause the game to crash. * Removed extraneous does_thread_exist deceleration.
This commit is contained in:
@ -1,123 +0,0 @@
|
||||
#include "locals_service.hpp"
|
||||
|
||||
#include "core/data/all_script_names.hpp"
|
||||
#include "fiber_pool.hpp"
|
||||
#include "natives.hpp"
|
||||
#include "pointers.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)
|
||||
{
|
||||
return SCRIPT::DOES_SCRIPT_WITH_NAME_HASH_EXIST(rage::joaat(script_name));
|
||||
}
|
||||
|
||||
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, 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"];
|
||||
new_local.m_edit_mode = j[l.key()].value<int>("editmode", 0);
|
||||
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;
|
||||
j[l.first]["editmode"] = l.second.m_edit_mode;
|
||||
|
||||
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";
|
||||
}
|
||||
}
|
||||
|
||||
};
|
@ -1,125 +0,0 @@
|
||||
#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;
|
||||
float m_freeze_value_float;
|
||||
Vector3 m_freeze_value_vector3;
|
||||
int* m_internal_address;
|
||||
Vector3* m_internal_address_vector3;
|
||||
int m_edit_mode = 0;
|
||||
|
||||
local(const char* script_thread_name, const char* name, const int base_address, const bool freeze, const int (*offsets)[2], int offset_count, int edit_mode = 0)
|
||||
{
|
||||
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]));
|
||||
|
||||
m_edit_mode = edit_mode;
|
||||
|
||||
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*>();
|
||||
m_internal_address_vector3 = actual_local.as<Vector3*>();
|
||||
|
||||
return m_internal_address;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const char* get_local_chain_text()
|
||||
{
|
||||
static char offsetschain[200] = "";
|
||||
strcpy(offsetschain, "");
|
||||
strcat(offsetschain, std::to_string(m_base_address).data());
|
||||
for (auto o : m_offsets)
|
||||
{
|
||||
strcat(offsetschain, std::string(".f_" + std::to_string(o.m_offset)).data());
|
||||
if (o.m_size)
|
||||
strcat(offsetschain, std::string("/" + std::to_string(o.m_size)).data());
|
||||
}
|
||||
return offsetschain;
|
||||
}
|
||||
|
||||
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