Redesigned Debug Globals. (#1696)
This commit is contained in:
parent
05a917bbbb
commit
5770466a84
@ -13,7 +13,6 @@
|
||||
#include "services/api/api_service.hpp"
|
||||
#include "services/context_menu/context_menu_service.hpp"
|
||||
#include "services/custom_text/custom_text_service.hpp"
|
||||
#include "services/globals/globals_service.hpp"
|
||||
#include "services/gta_data/gta_data_service.hpp"
|
||||
#include "services/gui/gui_service.hpp"
|
||||
#include "services/hotkey/hotkey_service.hpp"
|
||||
@ -93,7 +92,6 @@ BOOL APIENTRY DllMain(HMODULE hmod, DWORD reason, PVOID)
|
||||
|
||||
auto context_menu_service_instance = std::make_unique<context_menu_service>();
|
||||
auto custom_text_service_instance = std::make_unique<custom_text_service>();
|
||||
auto globals_service_instace = std::make_unique<globals_service>();
|
||||
auto mobile_service_instance = std::make_unique<mobile_service>();
|
||||
auto notification_service_instance = std::make_unique<notification_service>();
|
||||
auto pickup_service_instance = std::make_unique<pickup_service>();
|
||||
@ -197,8 +195,6 @@ BOOL APIENTRY DllMain(HMODULE hmod, DWORD reason, PVOID)
|
||||
LOG(INFO) << "Player Service reset.";
|
||||
pickup_service_instance.reset();
|
||||
LOG(INFO) << "Pickup Service reset.";
|
||||
globals_service_instace.reset();
|
||||
LOG(INFO) << "Globals Service reset.";
|
||||
custom_text_service_instance.reset();
|
||||
LOG(INFO) << "Custom Text Service reset.";
|
||||
context_menu_service_instance.reset();
|
||||
|
@ -1,78 +0,0 @@
|
||||
#include "globals_service.hpp"
|
||||
|
||||
#include "thread_pool.hpp"
|
||||
|
||||
namespace big
|
||||
{
|
||||
globals_service::globals_service() :
|
||||
m_globals_file(g_file_manager.get_project_file("./globals.json"))
|
||||
{ }
|
||||
|
||||
globals_service::~globals_service()
|
||||
{
|
||||
m_running = false;
|
||||
|
||||
save();
|
||||
}
|
||||
|
||||
void globals_service::build()
|
||||
{
|
||||
m_globals.clear();
|
||||
|
||||
for (auto& global : m_globals)
|
||||
global.build_cache();
|
||||
}
|
||||
|
||||
bool globals_service::load()
|
||||
{
|
||||
m_globals_file;
|
||||
|
||||
std::ifstream file(m_globals_file.get_path(), std::ios::binary);
|
||||
|
||||
if (!file.is_open())
|
||||
return false;
|
||||
|
||||
try
|
||||
{
|
||||
nlohmann::json j;
|
||||
file >> j;
|
||||
m_globals = j.get<global_vec>();
|
||||
|
||||
build();
|
||||
}
|
||||
catch (const std::exception&)
|
||||
{
|
||||
LOG(WARNING) << "Failure to parse globals.json, aborting...";
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void globals_service::loop()
|
||||
{
|
||||
while (m_running)
|
||||
for (auto& global : m_globals)
|
||||
if (global.m_freeze)
|
||||
global.write();
|
||||
}
|
||||
|
||||
void globals_service::save()
|
||||
{
|
||||
nlohmann::json j = m_globals;
|
||||
|
||||
std::ofstream file(m_globals_file.get_path(), std::ios::binary | std::ios::out | std::ios::trunc);
|
||||
|
||||
try
|
||||
{
|
||||
file << j.dump(4);
|
||||
|
||||
file.close();
|
||||
}
|
||||
catch (const std::exception&)
|
||||
{
|
||||
LOG(WARNING) << "Failed to write to globals.json";
|
||||
}
|
||||
}
|
||||
}
|
@ -1,114 +0,0 @@
|
||||
#pragma once
|
||||
#include "script_global.hpp"
|
||||
|
||||
namespace big
|
||||
{
|
||||
struct global_offset
|
||||
{
|
||||
int m_offset = 0;
|
||||
int m_size = 0;
|
||||
|
||||
global_offset() = default;
|
||||
global_offset(int offset, int size = 0)
|
||||
{
|
||||
m_offset = offset;
|
||||
|
||||
if (size)
|
||||
m_size = size;
|
||||
}
|
||||
|
||||
script_global apply(script_global internal_cache)
|
||||
{
|
||||
return m_size ? internal_cache.at(m_offset, m_size) : internal_cache.at(m_offset);
|
||||
}
|
||||
};
|
||||
NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(global_offset, m_offset, m_size)
|
||||
|
||||
struct global
|
||||
{
|
||||
int m_base_address;
|
||||
bool m_freeze = false;
|
||||
std::string m_name;
|
||||
std::vector<global_offset> m_offsets;
|
||||
int m_value;
|
||||
|
||||
global() = default;
|
||||
global(const char* name, const int base_address, const bool freeze, const int (*offsets)[2], int offset_count) :
|
||||
m_name(name),
|
||||
m_base_address(base_address),
|
||||
m_freeze(freeze)
|
||||
{
|
||||
m_internal_id = ++m_instance_count;
|
||||
|
||||
for (int i = 0; i < offset_count; ++i)
|
||||
{
|
||||
const auto offset = offsets[i];
|
||||
m_offsets.push_back({ offset[0], offset[1] });
|
||||
}
|
||||
}
|
||||
|
||||
void build_cache()
|
||||
{
|
||||
script_global internal_cache(m_base_address);
|
||||
|
||||
for (auto& offset : m_offsets)
|
||||
internal_cache = offset.apply(internal_cache);
|
||||
|
||||
m_internal_addr = internal_cache.as<int*>();
|
||||
}
|
||||
|
||||
int* get()
|
||||
{
|
||||
if (m_freeze)
|
||||
return &m_value;
|
||||
return m_internal_addr;
|
||||
}
|
||||
|
||||
int get_id()
|
||||
{
|
||||
return m_internal_id;
|
||||
}
|
||||
|
||||
void set(int value)
|
||||
{
|
||||
m_value = value;
|
||||
if (!m_freeze)
|
||||
this->write();
|
||||
}
|
||||
|
||||
void write()
|
||||
{
|
||||
*m_internal_addr = m_value;
|
||||
}
|
||||
|
||||
private:
|
||||
inline static int m_instance_count;
|
||||
|
||||
int m_internal_id;
|
||||
int* m_internal_addr;
|
||||
};
|
||||
NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(global, m_base_address, m_freeze, m_offsets, m_name, m_value)
|
||||
|
||||
using global_vec = std::vector<global>;
|
||||
class globals_service
|
||||
{
|
||||
file m_globals_file;
|
||||
|
||||
public:
|
||||
globals_service();
|
||||
~globals_service();
|
||||
|
||||
bool load();
|
||||
void loop();
|
||||
void save();
|
||||
|
||||
global_vec m_globals;
|
||||
bool m_running = false;
|
||||
|
||||
private:
|
||||
void build();
|
||||
|
||||
};
|
||||
|
||||
inline auto g_globals_service = globals_service();
|
||||
}
|
@ -1,148 +1,254 @@
|
||||
#include "gui/components/components.hpp"
|
||||
#include "services/globals/globals_service.hpp"
|
||||
#include "script_global.hpp"
|
||||
#include "thread_pool.hpp"
|
||||
#include "view_debug.hpp"
|
||||
|
||||
namespace big
|
||||
{
|
||||
enum GlobalAppendageType : int
|
||||
{
|
||||
GlobalAppendageType_At,
|
||||
GlobalAppendageType_ReadGlobal,
|
||||
GlobalAppendageType_PlayerId,
|
||||
};
|
||||
|
||||
struct global_debug_inner
|
||||
{
|
||||
GlobalAppendageType type{};
|
||||
std::ptrdiff_t index{};
|
||||
std::size_t size{};
|
||||
std::string global_name{};
|
||||
|
||||
NLOHMANN_DEFINE_TYPE_INTRUSIVE(global_debug_inner, type, index, size, global_name)
|
||||
};
|
||||
|
||||
struct global_debug
|
||||
{
|
||||
std::size_t global_index{};
|
||||
std::vector<global_debug_inner> global_appendages{};
|
||||
|
||||
NLOHMANN_DEFINE_TYPE_INTRUSIVE(global_debug, global_index, global_appendages)
|
||||
};
|
||||
|
||||
nlohmann::json get_globals_json()
|
||||
{
|
||||
nlohmann::json globals{};
|
||||
|
||||
auto file = g_file_manager.get_project_file("./globals.json");
|
||||
if (file.exists())
|
||||
{
|
||||
std::ifstream iffstream_file(file.get_path());
|
||||
iffstream_file >> globals;
|
||||
}
|
||||
|
||||
return globals;
|
||||
}
|
||||
|
||||
void load_global_menu(const std::string& selected_global, global_debug& global_obj)
|
||||
{
|
||||
if (!selected_global.empty())
|
||||
{
|
||||
auto globals = get_globals_json();
|
||||
if (globals[selected_global].is_null())
|
||||
return;
|
||||
global_obj = globals[selected_global].get<global_debug>();
|
||||
}
|
||||
}
|
||||
|
||||
int64_t* get_global_ptr(global_debug& global_test)
|
||||
{
|
||||
script_global global_to_read = script_global(global_test.global_index);
|
||||
for (auto item : global_test.global_appendages)
|
||||
{
|
||||
if (item.type == GlobalAppendageType_At)
|
||||
{
|
||||
if (item.size != 0)
|
||||
global_to_read = global_to_read.at(item.index, item.size);
|
||||
else
|
||||
global_to_read = global_to_read.at(item.index);
|
||||
}
|
||||
else if (item.type == GlobalAppendageType_ReadGlobal)
|
||||
{
|
||||
global_debug global_read;
|
||||
load_global_menu(item.global_name, global_read);
|
||||
if (auto ptr = get_global_ptr(global_read))
|
||||
if (item.size != 0)
|
||||
global_to_read = global_to_read.at(*ptr, item.size);
|
||||
else
|
||||
global_to_read = global_to_read.at(*ptr);
|
||||
else
|
||||
LOG(WARNING) << "Failed to read " << item.global_name << "for get_global_ptr";
|
||||
}
|
||||
else if (item.type == GlobalAppendageType_PlayerId)
|
||||
{
|
||||
if (item.size != 0)
|
||||
global_to_read = global_to_read.at(self::id, item.size);
|
||||
else
|
||||
global_to_read = global_to_read.at(self::id);
|
||||
}
|
||||
}
|
||||
auto retn_val = global_to_read.as<int64_t*>();
|
||||
if ((size_t)retn_val < UINT32_MAX)
|
||||
return nullptr;
|
||||
return retn_val;
|
||||
}
|
||||
|
||||
std::map<std::string, global_debug> list_globals()
|
||||
{
|
||||
auto json = get_globals_json();
|
||||
std::map<std::string, global_debug> return_value;
|
||||
for (auto& item : json.items())
|
||||
return_value[item.key()] = item.value();
|
||||
return return_value;
|
||||
}
|
||||
|
||||
void save_global(char* global_name, global_debug& global_obj)
|
||||
{
|
||||
std::string teleport_name_string = global_name;
|
||||
if (!teleport_name_string.empty())
|
||||
{
|
||||
auto json = get_globals_json();
|
||||
json[global_name] = global_obj;
|
||||
|
||||
auto file_path = g_file_manager.get_project_file("./globals.json").get_path();
|
||||
std::ofstream file(file_path, std::ios::out | std::ios::trunc);
|
||||
file << json.dump(4);
|
||||
file.close();
|
||||
ZeroMemory(global_name, sizeof(global_name));
|
||||
}
|
||||
}
|
||||
|
||||
void delete_global(std::string name)
|
||||
{
|
||||
auto locations = get_globals_json();
|
||||
if (locations[name].is_null())
|
||||
return;
|
||||
locations.erase(name);
|
||||
auto file_path = g_file_manager.get_project_file("./globals.json").get_path();
|
||||
std::ofstream file(file_path, std::ios::out | std::ios::trunc);
|
||||
file << locations.dump(4);
|
||||
file.close();
|
||||
}
|
||||
|
||||
void debug::globals()
|
||||
{
|
||||
if (ImGui::BeginTabItem("DEBUG_TAB_GLOBALS"_T.data()))
|
||||
{
|
||||
if (ImGui::Checkbox("DEBUG_GLOBALS_ENABLE_FREEZING"_T.data(), &g_globals_service.m_running)
|
||||
&& g_globals_service.m_running)
|
||||
g_thread_pool->push([&]() {
|
||||
g_globals_service.loop();
|
||||
});
|
||||
|
||||
if (components::button("LOAD"_T))
|
||||
g_globals_service.load();
|
||||
ImGui::SameLine();
|
||||
if (components::button("SAVE"_T))
|
||||
g_globals_service.save();
|
||||
|
||||
|
||||
ImGui::SameLine();
|
||||
if (components::button("DEBUG_GLOBALS_ADD"_T))
|
||||
{
|
||||
ImGui::OpenPopup("DEBUG_GLOBALS_NEW"_T.data());
|
||||
}
|
||||
|
||||
if (ImGui::BeginPopupModal("DEBUG_GLOBALS_NEW"_T.data()))
|
||||
{
|
||||
static int base_address = 0;
|
||||
static bool freeze = false;
|
||||
static char name[32] = "";
|
||||
static int offsets[10][2] = {};
|
||||
static int offset_count = 0;
|
||||
static int previous_offset_count = 0;
|
||||
|
||||
ImGui::Text("DEBUG_GLOBALS_NAME"_T.data());
|
||||
components::input_text_with_hint("##global_name", "Name", name, sizeof(name));
|
||||
ImGui::Text("DEBUG_GLOBALS_BASE_ADDRESS"_T.data());
|
||||
ImGui::InputInt("##modal_global_base_addr", &base_address);
|
||||
ImGui::Text("DEBUG_GLOBAL_FREEZE"_T.data());
|
||||
ImGui::Checkbox("##modal_global_freeze", &freeze);
|
||||
ImGui::Text("DEBUG_GLOBAL_OFFSET_COUNT"_T.data());
|
||||
ImGui::InputInt("##modal_offset_count", &offset_count);
|
||||
|
||||
offset_count = std::clamp(offset_count, 0, 10);
|
||||
|
||||
ImGui::PushItemWidth(320.f);
|
||||
for (int i = 0; i < offset_count; i++)
|
||||
{
|
||||
ImGui::PushID(i);
|
||||
|
||||
ImGui::Separator();
|
||||
|
||||
ImGui::Text("DEBUG_GLOBAL_OFFSET"_T.data(), i + 1);
|
||||
ImGui::InputInt("##offset", &offsets[i][0]);
|
||||
|
||||
ImGui::Text("DEBUG_GLOBAL_SIZE"_T.data());
|
||||
ImGui::SameLine();
|
||||
ImGui::InputInt("##size", &offsets[i][1]);
|
||||
|
||||
ImGui::PopID();
|
||||
}
|
||||
ImGui::PopItemWidth();
|
||||
|
||||
if (components::button("CANCEL"_T))
|
||||
{
|
||||
strcpy(name, "");
|
||||
freeze = false;
|
||||
offset_count = 0;
|
||||
previous_offset_count = 0;
|
||||
|
||||
ImGui::CloseCurrentPopup();
|
||||
}
|
||||
ImGui::SameLine();
|
||||
if (components::button("SAVE"_T))
|
||||
{
|
||||
auto new_global = global(name, base_address, freeze, offsets, offset_count);
|
||||
new_global.build_cache();
|
||||
|
||||
g_globals_service.m_globals.push_back(new_global);
|
||||
|
||||
strcpy(name, "");
|
||||
freeze = false;
|
||||
offset_count = 0;
|
||||
previous_offset_count = 0;
|
||||
|
||||
ImGui::CloseCurrentPopup();
|
||||
}
|
||||
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
|
||||
for (auto& global : g_globals_service.m_globals)
|
||||
{
|
||||
char label[64];
|
||||
|
||||
ImGui::Separator();
|
||||
|
||||
ImGui::PushID(global.get_id());
|
||||
ImGui::Checkbox("DEBUG_GLOBAL_FREEZE_TOGGLE"_T.data(), &global.m_freeze);
|
||||
|
||||
ImGui::BeginGroup();
|
||||
|
||||
ImGui::Text("DEBUG_GLOBALS_NAME"_T.data());
|
||||
ImGui::Text("DEBUG_GLOBALS_VALUE"_T.data());
|
||||
|
||||
ImGui::EndGroup();
|
||||
|
||||
ImGui::SameLine();
|
||||
|
||||
ImGui::BeginGroup();
|
||||
|
||||
ImGui::Text(global.m_name.c_str());
|
||||
|
||||
sprintf(label, "###input_%d", global.get_id());
|
||||
static global_debug global_test{};
|
||||
static script_global glo_bal_sunday = script_global(global_test.global_index);
|
||||
ImGui::SetNextItemWidth(200.f);
|
||||
ImGui::InputInt(label, global.get());
|
||||
if (ImGui::InputScalar("Global", ImGuiDataType_U64, &global_test.global_index))
|
||||
glo_bal_sunday = script_global(global_test.global_index);
|
||||
|
||||
ImGui::EndGroup();
|
||||
|
||||
ImGui::SameLine();
|
||||
|
||||
ImGui::BeginGroup();
|
||||
|
||||
if (components::button("DELETE"_T))
|
||||
for (int i = 0; i < global_test.global_appendages.size(); i++)
|
||||
{
|
||||
for (int i = 0; i < g_globals_service.m_globals.size(); i++)
|
||||
if (auto& it = g_globals_service.m_globals.at(i); it.get_id() == global.get_id())
|
||||
g_globals_service.m_globals.erase(g_globals_service.m_globals.begin() + i);
|
||||
|
||||
auto item = global_test.global_appendages[i];
|
||||
switch (item.type)
|
||||
{
|
||||
case GlobalAppendageType_At:
|
||||
ImGui::SetNextItemWidth(200.f);
|
||||
ImGui::InputScalar(std::format("At##{}{}", i, (int)item.type).c_str(),
|
||||
ImGuiDataType_S64,
|
||||
&global_test.global_appendages[i].index);
|
||||
ImGui::SameLine();
|
||||
ImGui::SetNextItemWidth(200.f);
|
||||
ImGui::InputScalar(std::format("Size##{}{}", i, (int)item.type).c_str(),
|
||||
ImGuiDataType_S64,
|
||||
&global_test.global_appendages[i].size);
|
||||
break;
|
||||
case GlobalAppendageType_ReadGlobal:
|
||||
ImGui::Text(std::format("Read Global {}", item.global_name).c_str());
|
||||
ImGui::SameLine();
|
||||
ImGui::SetNextItemWidth(200.f);
|
||||
ImGui::InputScalar(std::format("Size##{}{}", i, (int)item.type).c_str(),
|
||||
ImGuiDataType_S64,
|
||||
&global_test.global_appendages[i].size);
|
||||
break;
|
||||
case GlobalAppendageType_PlayerId:
|
||||
ImGui::SetNextItemWidth(200.f);
|
||||
ImGui::InputScalar(std::format("Read Player ID Size##{}{}", i, (int)item.type).c_str(),
|
||||
ImGuiDataType_S64,
|
||||
&global_test.global_appendages[i].size);
|
||||
break;
|
||||
}
|
||||
|
||||
if (components::button("WRITE"_T))
|
||||
global.write();
|
||||
|
||||
ImGui::PopID();
|
||||
ImGui::EndGroup();
|
||||
}
|
||||
|
||||
ImGui::EndTabItem();
|
||||
if (ImGui::Button("Add Offset"))
|
||||
global_test.global_appendages.push_back({GlobalAppendageType_At, 0LL, 0ULL});
|
||||
ImGui::SameLine();
|
||||
if (ImGui::Button("Add Read Player Id"))
|
||||
global_test.global_appendages.push_back({GlobalAppendageType_PlayerId, 0LL, 0ULL});
|
||||
|
||||
if (global_test.global_appendages.size() > 0 && ImGui::Button("Remove Offset"))
|
||||
global_test.global_appendages.pop_back();
|
||||
|
||||
if (auto ptr = get_global_ptr(global_test))
|
||||
{
|
||||
ImGui::SetNextItemWidth(200.f);
|
||||
ImGui::InputScalar("Value", ImGuiDataType_S64, ptr);
|
||||
}
|
||||
else
|
||||
ImGui::Text("INVALID_GLOBAL_READ");
|
||||
|
||||
auto globals = list_globals();
|
||||
static std::string selected_global;
|
||||
ImGui::Text("Saved Globals");
|
||||
if (ImGui::BeginListBox("##savedglobals", ImVec2(200, 200)))
|
||||
{
|
||||
for (auto pair : globals)
|
||||
{
|
||||
if (ImGui::Selectable(pair.first.c_str(), selected_global == pair.first))
|
||||
selected_global = std::string(pair.first);
|
||||
}
|
||||
ImGui::EndListBox();
|
||||
}
|
||||
ImGui::SameLine();
|
||||
if (ImGui::BeginListBox("##globalvalues", ImVec2(200, 200)))
|
||||
{
|
||||
for (auto pair : globals)
|
||||
{
|
||||
if (auto ptr = get_global_ptr(pair.second))
|
||||
ImGui::Selectable(std::format("{}", *ptr).c_str(), false, ImGuiSelectableFlags_Disabled);
|
||||
else
|
||||
ImGui::Selectable("INVALID_GLOBAL_READ", false, ImGuiSelectableFlags_Disabled);
|
||||
}
|
||||
ImGui::EndListBox();
|
||||
}
|
||||
ImGui::SameLine();
|
||||
ImGui::BeginGroup();
|
||||
static char global_name[50]{};
|
||||
ImGui::SetNextItemWidth(200.f);
|
||||
ImGui::InputText("##GlobalName", global_name, IM_ARRAYSIZE(global_name));
|
||||
if (ImGui::Button("Save Global"))
|
||||
{
|
||||
save_global(global_name, global_test);
|
||||
}
|
||||
ImGui::SameLine();
|
||||
if (ImGui::Button("Load Global"))
|
||||
{
|
||||
load_global_menu(selected_global, global_test);
|
||||
}
|
||||
|
||||
if (ImGui::Button("Delete Global"))
|
||||
{
|
||||
if (!selected_global.empty())
|
||||
{
|
||||
delete_global(selected_global);
|
||||
selected_global.clear();
|
||||
}
|
||||
}
|
||||
ImGui::SameLine();
|
||||
if (ImGui::Button("Add Read Global"))
|
||||
{
|
||||
global_test.global_appendages.push_back({GlobalAppendageType_ReadGlobal, 0LL, 0ULL, selected_global});
|
||||
}
|
||||
ImGui::SameLine();
|
||||
if (ImGui::Button("Clear"))
|
||||
{
|
||||
global_test.global_index = 0;
|
||||
global_test.global_appendages.clear();
|
||||
}
|
||||
ImGui::EndGroup();
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user