Finish switch to toml, fix hotkey saving

This commit is contained in:
Grinch_ 2022-06-16 16:40:46 +06:00
parent 9613354939
commit 6dfadd3470
23 changed files with 360 additions and 25851 deletions

File diff suppressed because it is too large Load Diff

102
depend/toml_addon.hpp Normal file
View File

@ -0,0 +1,102 @@
#pragma once
#include "toml.hpp"
template <typename T, typename Path>
auto build_from_path(T&& value, Path&& path_component)
{
using component_type = std::remove_cv_t<std::remove_reference_t<Path>>;
static_assert(std::is_integral_v<component_type> || toml::is_key_or_convertible<Path&&>,
"path components must be integers or strings");
// making an array
if constexpr (std::is_integral_v<component_type>)
{
toml::array arr;
const auto index = static_cast<std::size_t>(path_component);
arr.reserve(index + 1u);
// backfill with integers
while (arr.size() < index)
arr.push_back(0);
// add the actual value
arr.push_back(static_cast<T&&>(value));
return arr;
}
else // making a table
{
toml::table tbl;
tbl.insert_or_assign(path_component, value);
return tbl;
}
}
template <typename T, typename Path, typename... Paths>
auto build_from_path(T&& value, Path&& path_component, Paths&&... path_components)
{
static_assert(sizeof...(Paths));
return build_from_path(build_from_path(value, path_components...), path_component);
}
static void merge_left(toml::table& lhs, toml::table&& rhs);
static void merge_left(toml::array& lhs, toml::array&& rhs)
{
rhs.for_each(
[&](std::size_t index, auto&& rhs_val)
{
// rhs index not found in lhs - direct move
if (lhs.size() <= index)
{
lhs.push_back(std::move(rhs_val));
return;
}
// both elements were the same container type - recurse into them
if constexpr (toml::is_container<decltype(rhs_val)>)
{
using rhs_type = std::remove_cv_t<std::remove_reference_t<decltype(rhs_val)>>;
if (auto lhs_child = lhs[index].as<rhs_type>())
{
merge_left(*lhs_child, std::move(rhs_val));
return;
}
}
// replace lhs element with rhs
lhs.replace(lhs.cbegin() + index, std::move(rhs_val));
});
}
static void merge_left(toml::table& lhs, toml::table&& rhs)
{
rhs.for_each(
[&](const toml::key& rhs_key, auto&& rhs_val)
{
auto lhs_it = lhs.lower_bound(rhs_key);
// rhs key not found in lhs - direct move
if (lhs_it == lhs.cend() || lhs_it->first != rhs_key)
{
using rhs_type = std::remove_cv_t<std::remove_reference_t<decltype(rhs_val)>>;
lhs.emplace_hint<rhs_type>(lhs_it, rhs_key, std::move(rhs_val));
return;
}
// both children were the same container type - recurse into them
if constexpr (toml::is_container<decltype(rhs_val)>)
{
using rhs_type = std::remove_cv_t<std::remove_reference_t<decltype(rhs_val)>>;
if (auto lhs_child = lhs_it->second.as<rhs_type>())
{
merge_left(*lhs_child, std::move(rhs_val));
return;
}
}
// replace lhs value with rhs
lhs.insert_or_assign(rhs_key, std::move(rhs_val));
});
}

View File

@ -4,7 +4,7 @@
# #
# [Category Name] # [Category Name]
# location_name = "interior_id, position_x, position_y, position_z" # location_name = "interior_id, position_x, position_y, position_z"
######### ##############################################################################
[Custom] [Custom]

View File

@ -1,90 +1,93 @@
############################################################################## ##############################################################################
# Particle Names # Particle Names
# Example: Category = ["name1", "name2"] # Example,
# [Category Name]
# particle_name = ""
############################################################################## ##############################################################################
Custom = [] [Custom]
Main = [
"prt_blood", [Main]
"prt_boatsplash", prt_blood = ""
"prt_bubbles", prt_boatsplash = ""
"prt_cardebris", prt_bubbles = ""
"prt_collisionsmoke", prt_cardebris = ""
"prt_glass", prt_collisionsmoke = ""
"prt_gunshell", prt_glass = ""
"prt_sand", prt_gunshell = ""
"prt_sand2", prt_sand = ""
"prt_smokeII_3_expand", prt_sand2 = ""
"prt_smoke_huge", prt_smokeII_3_expand = ""
"prt_spark", prt_smoke_huge = ""
"prt_spark2", prt_spark = ""
"prt_splash", prt_spark2 = ""
"prt_wake", prt_splash = ""
"prt_watersplash", prt_wake = ""
"prt_wheeldirt", prt_watersplash = ""
"boat_prop", prt_wheeldirt = ""
"camflash", boat_prop = ""
"exhale", camflash = ""
"explosion_fuel_car", exhale = ""
"explosion_large", explosion_fuel_car = ""
"explosion_medium", explosion_large = ""
"explosion_molotov", explosion_medium = ""
"explosion_small", explosion_molotov = ""
"explosion_tiny", explosion_small = ""
"extinguisher", explosion_tiny = ""
"fire", extinguisher = ""
"fire_bike", fire = ""
"fire_car", fire_bike = ""
"fire_large", fire_car = ""
"fire_med", fire_large = ""
"flamethrower", fire_med = ""
"gunflash", flamethrower = ""
"gunsmoke", gunflash = ""
"heli_dust", gunsmoke = ""
"jetpack", heli_dust = ""
"jetthrust", jetpack = ""
"molotov_flame", jetthrust = ""
"nitro", molotov_flame = ""
"overheat_car", nitro = ""
"overheat_car_electric", overheat_car = ""
"riot_smoke", overheat_car_electric = ""
"spraycan", riot_smoke = ""
"tank_fire", spraycan = ""
"teargas", tank_fire = ""
"teargasAD", teargas = ""
"water_hydrant", teargasAD = ""
"water_ripples", water_hydrant = ""
"water_speed", water_ripples = ""
"water_splash", water_speed = ""
"water_splsh_big", water_splash = ""
"water_splsh_sml", water_splsh_big = ""
"water_swim", water_splsh_sml = ""
"cigarette_smoke", water_swim = ""
"flame", cigarette_smoke = ""
"insects", flame = ""
"smoke30lit", insects = ""
"smoke30m", smoke30lit = ""
"smoke50lit", smoke30m = ""
"vent", smoke50lit = ""
"vent2", vent = ""
"waterfall_end", vent2 = ""
"water_fnt_tme", waterfall_end = ""
"water_fountain", water_fnt_tme = ""
"tree_hit_fir", water_fountain = ""
"tree_hit_palm", tree_hit_fir = ""
"blood_heli", tree_hit_palm = ""
"carwashspray", blood_heli = ""
"cement", carwashspray = ""
"cloudfast", cement = ""
"coke_puff", cloudfast = ""
"coke_trail", coke_puff = ""
"explosion_barrel", coke_trail = ""
"explosion_crate", explosion_barrel = ""
"explosion_door", explosion_crate = ""
"petrolcan", explosion_door = ""
"puke", petrolcan = ""
"shootlight", puke = ""
"smoke_flare", shootlight = ""
"wallbust", smoke_flare = ""
"ws_factorysmoke" wallbust = ""
] ws_factorysmoke = ""

View File

@ -143,7 +143,7 @@
"InvalidValue": "Invalid value", "InvalidValue": "Invalid value",
"Language": "Language", "Language": "Language",
"LanguageChangeFailed": "Failed to change language!", "LanguageChangeFailed": "Failed to change language!",
"LatestVersion" : "Latest version", "LatestVersion" : "Latest version: ",
"Location": "Location: %s", "Location": "Location: %s",
"Name": "Name", "Name": "Name",
"NewVersion" : "A new version of the menu is available.", "NewVersion" : "A new version of the menu is available.",

View File

@ -53,8 +53,8 @@ void CheatMenu::DrawWindow()
else else
m_fMenuSize = ImGui::GetWindowSize(); m_fMenuSize = ImGui::GetWindowSize();
gConfig.SetValue("window.sizeX", m_fMenuSize.x); gConfig.Set("Window.SizeX", m_fMenuSize.x);
gConfig.SetValue("window.sizeY", m_fMenuSize.y); gConfig.Set("Window.SizeY", m_fMenuSize.y);
ImGui::PopStyleVar(2); ImGui::PopStyleVar(2);
ImGui::End(); ImGui::End();
@ -94,11 +94,11 @@ void CheatMenu::ProcessPages()
* We don't want to be annoying and * We don't want to be annoying and
* show anniversary screen on every game start * show anniversary screen on every game start
*/ */
bool flag = gConfig.GetValue("window.anniversaryShown", false); bool flag = gConfig.Get("Window.AnniversaryShown", false);
if (!flag) if (!flag)
{ {
gConfig.SetValue("window.anniversaryShown", true); gConfig.Set("Window.AnniversaryShown", true);
m_nMenuPage = eMenuPages::ANNIVERSARY; m_nMenuPage = eMenuPages::ANNIVERSARY;
} }
} }
@ -137,7 +137,7 @@ void CheatMenu::ProcessPages()
{ {
m_nMenuPage = m_headerList[i].page; m_nMenuPage = m_headerList[i].page;
size_t curPage = static_cast<size_t>(m_headerList[i].page); size_t curPage = static_cast<size_t>(m_headerList[i].page);
gConfig.SetValue("window.page", curPage); gConfig.Set("Window.CurrentPage", curPage);
pCallback = m_headerList[i].pFunc; pCallback = m_headerList[i].pFunc;
Updater::ResetUpdaterState(); Updater::ResetUpdaterState();
} }
@ -210,9 +210,9 @@ void CheatMenu::Init()
} }
// Load menu settings // Load menu settings
m_nMenuPage = (eMenuPages)gConfig.GetValue("window.page", (size_t)eMenuPages::WELCOME); m_nMenuPage = (eMenuPages)gConfig.Get("Window.CurrentPage", (size_t)eMenuPages::WELCOME);
m_fMenuSize.x = gConfig.GetValue("window.sizeX", screen::GetScreenWidth() / 4.0f); m_fMenuSize.x = gConfig.Get("Window.SizeX", screen::GetScreenWidth() / 4.0f);
m_fMenuSize.y = gConfig.GetValue("window.sizeY", screen::GetScreenHeight() / 1.2f); m_fMenuSize.y = gConfig.Get("Window.SizeY", screen::GetScreenHeight() / 1.2f);
srand(CTimer::m_snTimeInMilliseconds); srand(CTimer::m_snTimeInMilliseconds);
ApplyStyle(); ApplyStyle();

View File

@ -1,10 +1,16 @@
#include "datastore.h" #include "datastore.h"
#include "pch.h" #include "pch.h"
DataStore::DataStore(const char* fileName, bool isConfig) noexcept DataStore::DataStore(const char* fileName, bool isPathPredefined) noexcept
{ {
// Output config file in the same directory as the asi if (isPathPredefined)
path = PLUGIN_PATH((char*)(isConfig ? "/" : "/CheatMenu/data/")) + std::string(fileName) + fileExt; {
path = std::string(fileName) + fileExt;
}
else
{
path = PLUGIN_PATH((char*)"/CheatMenu/data/") + std::string(fileName) + fileExt;
}
if (std::filesystem::exists(path)) if (std::filesystem::exists(path))
{ {
@ -21,7 +27,7 @@ DataStore::DataStore(const char* fileName, bool isConfig) noexcept
{ {
pTable = std::make_unique<toml::table>(); pTable = std::make_unique<toml::table>();
if (isConfig) if (fileName == FILE_NAME)
{ {
Log::Print<eLogLevel::Info>("Creating {}{}", fileName, fileExt); Log::Print<eLogLevel::Info>("Creating {}{}", fileName, fileExt);
} }
@ -59,7 +65,7 @@ void DataStore::RemoveKey(const char* key, const char* entry) noexcept
{ {
if (pTable) if (pTable)
{ {
(*pTable)[key].as_table()->erase(entry); (*pTable).at_path(key).as_table()->erase(entry);
} }
} }

View File

@ -1,8 +1,9 @@
#pragma once #pragma once
#define TOML_EXCEPTIONS 0 #define TOML_EXCEPTIONS 0
#include "../depend/toml.hpp" #include "../depend/toml_addon.hpp"
#include <memory> #include <memory>
/* /*
DataStore Class DataStore Class
Stores & loads data from disk Stores & loads data from disk
@ -18,44 +19,63 @@ private:
public: public:
typedef toml::table Table; typedef toml::table Table;
DataStore(const char* fileName, bool isConfig = false) noexcept; DataStore(const char* fileName, bool isPathPredefined = false) noexcept;
// Returns data from store structure // Returns data from store structure
std::string Get(const char* key, const char* defaultVal) noexcept
{
if (pTable)
{
return (*pTable).at_path(key).value_or(defaultVal);
}
return defaultVal;
}
template<typename T> template<typename T>
T Get(const char* key, const T& defaultVal) noexcept T Get(const char* key, const T& defaultVal) noexcept
{ {
if (pTable) if (pTable)
{ {
return (*pTable)[key].value_or(defaultVal); return (*pTable).at_path(key).value_or(defaultVal);
} }
return defaultVal; return defaultVal;
} }
std::string Get(const char* key, std::string&& defaultVal) noexcept // Adds data to the structure
template <typename T>
void Set(const char* key, T&& value)
{ {
if (pTable) std::stringstream ss(key);
{ std::vector<std::string> paths;
return (*pTable)[key].value_or(defaultVal);
}
return defaultVal;
}
// Sets data in store structure while(ss.good())
template<typename T>
void Set(const char* key, const T& value) noexcept
{
if (pTable)
{ {
(*pTable)[key] = value; std::string s1 = "";
getline(ss, s1, '.');
if (s1 != "")
{
paths.push_back(std::move(s1));
}
} }
}
void Set(const char* key, std::string&& value) noexcept // assign the value
{ toml::table tbl;
if (pTable) int startIndex = paths.size()-1;
for (int i = startIndex; i >= 0; --i)
{ {
(*pTable)[key].ref<std::string>() = value; if (i == startIndex)
{
tbl.insert_or_assign(paths[i], std::move(value));
}
else
{
toml::table temp;
temp.insert_or_assign(paths[i], std::move(tbl));
tbl = std::move(temp);
}
} }
merge_left(*pTable, std::move(tbl));
} }
// If store contains element // If store contains element

View File

@ -9,7 +9,7 @@
#define MENU_NAME "Cheat Menu" #define MENU_NAME "Cheat Menu"
#define MENU_VERSION_NUMBER "3.3" #define MENU_VERSION_NUMBER "3.3"
#define MENU_VERSION MENU_VERSION_NUMBER"-beta" #define MENU_VERSION MENU_VERSION_NUMBER"-beta"
#define BUILD_NUMBER "20220612" #define BUILD_NUMBER "20220616"
#define MENU_TITLE MENU_NAME " v" MENU_VERSION #define MENU_TITLE MENU_NAME " v" MENU_VERSION
#ifdef GTASA #ifdef GTASA

View File

@ -69,18 +69,18 @@ void MenuThread(void* param)
} }
#endif #endif
Log::Print<eLogLevel::None>("\nVersion: " MENU_TITLE "\nAuthor: Grinch_\nDiscord: " DISCORD_INVITE "\nMore Info: " GITHUB_LINK "\n"); Log::Print<eLogLevel::None>("Version: " MENU_TITLE "\nAuthor: Grinch_\nDiscord: " DISCORD_INVITE "\nMore Info: " GITHUB_LINK "\n");
CheatMenu::Init(); CheatMenu::Init();
// Checking for updates once a day // Checking for updates once a day
SYSTEMTIME st; SYSTEMTIME st;
GetSystemTime(&st); GetSystemTime(&st);
if (gConfig.GetValue("config.update_date", 0) != st.wDay) if (gConfig.Get("config.update_date", 0) != st.wDay)
{ {
Updater::CheckUpdate(); Updater::CheckUpdate();
Updater::IncrementDailyUsageCounter(); Updater::IncrementDailyUsageCounter();
gConfig.SetValue("config.update_date", st.wDay); gConfig.Set("config.update_date", st.wDay);
} }
while (true) while (true)

View File

@ -4,7 +4,7 @@
class Game class Game
{ {
private: private:
static inline ResourceStore m_MissionData{ "mission", eResourceType::TYPE_TEXT }; static inline ResourceStore m_MissionData{ "missions", eResourceType::TYPE_TEXT };
static inline bool m_bDisableCheats; static inline bool m_bDisableCheats;
static inline bool m_bDisableReplay; static inline bool m_bDisableReplay;
static inline bool m_bMissionTimer; static inline bool m_bMissionTimer;

View File

@ -179,8 +179,8 @@ Hotkey::Hotkey(int key1, int key2, const std::string& configPath)
{ {
if (m_ConfigPath != "") if (m_ConfigPath != "")
{ {
m_key1 = gConfig.GetValue(m_ConfigPath + ".1", m_key1); m_key1 = gConfig.Get((m_ConfigPath + ".Key1").c_str(), m_key1);
m_key2 = gConfig.GetValue(m_ConfigPath + ".2", m_key2); m_key2 = gConfig.Get((m_ConfigPath + ".Key2").c_str(), m_key2);
} }
} }
@ -232,8 +232,8 @@ bool Hotkey::DrawUI(const char* label)
// Save the hotkeys in config file // Save the hotkeys in config file
if (m_ConfigPath != "") if (m_ConfigPath != "")
{ {
gConfig.SetValue(m_ConfigPath + "1", m_key1); gConfig.Set((m_ConfigPath + ".Key1").c_str(), m_key1);
gConfig.SetValue(m_ConfigPath + "2", m_key2); gConfig.Set((m_ConfigPath + ".Key2").c_str(), m_key2);
} }
} }

View File

@ -1,54 +0,0 @@
#include "json.h"
#include "pch.h"
CJson::CJson(const char* name, bool pathPredefined)
{
if (name == "" || !std::filesystem::is_directory(PLUGIN_PATH((char*)"CheatMenu")))
{
return;
}
if (pathPredefined)
{
m_FilePath = name;
}
else
{
m_FilePath = PLUGIN_PATH((char*)"/CheatMenu/json/") + std::string(name) + ".json";
}
if (std::filesystem::exists(m_FilePath))
{
try
{
std::ifstream file(m_FilePath);
file >> m_Data;
file.close();
}
catch (...)
{
//gLog << "Error trying to read " << m_FilePath << std::endl;
m_Data = "{}"_json;
}
}
else
{
m_Data = "{}"_json;
if (m_FilePath.find("config"))
{
//gLog << "Creating config.json file" << std::endl;
}
else
{
//gLog << "Failed to locate file " << m_FilePath << std::endl;
}
}
}
void CJson::Save()
{
std::ofstream file(m_FilePath);
file << m_Data.dump(4, ' ', false, nlohmann::json::error_handler_t::replace) << std::endl;
file.close();
}

View File

@ -1,122 +0,0 @@
#pragma once
#include "../depend/json.hpp"
/*
Wrapper class for nlohmann::json
Contains helper methods
*/
class CJson
{
private:
std::string m_FilePath;
public:
nlohmann::json m_Data;
/*
Returns a value from json structure hierarchy using '.'
Example: "Menu.Window.X"
*/
// specialize since typeid(std::string) doesn't work
template <typename T>
T inline GetValue(std::string&& key, const T& defaultVal)
{
try
{
std::stringstream ss(key);
std::string line;
nlohmann::json* json = &m_Data;
while (getline(ss, line, '.'))
{
json = &((*json)[line]);
}
// json library bugs with bool, using int instead
if (typeid(T) == typeid(bool))
{
return ((json->get<int>() == 1) ? true : false);
}
return json->get<T>();
}
catch (...)
{
return defaultVal;
}
}
std::string inline GetValueStr(const std::string& key, const std::string& defaultVal)
{
try
{
std::stringstream ss(key);
std::string line;
nlohmann::json* json = &m_Data;
while (getline(ss, line, '.'))
{
json = &((*json)[line]);
}
return json->get<std::string>();
}
catch (...)
{
return defaultVal;
}
}
/*
Allows to save values in json hierarchy using '.'
Example: "Menu.Window.X"
*/
template <typename T>
void inline SetValue(std::string&& key, const T& val)
{
std::stringstream ss(key);
std::string line;
nlohmann::json* json = &m_Data;
while (getline(ss, line, '.'))
{
json = &((*json)[line]);
}
// json library bugs with bool, using int instead
if (typeid(T) == typeid(bool))
{
*json = (val ? 1 : 0);
}
else
{
*json = val;
}
}
template <>
void inline SetValue(std::string&& key, const std::string& val)
{
std::stringstream ss(key);
std::string line;
nlohmann::json* json = &m_Data;
while (getline(ss, line, '.'))
{
json = &((*json)[line]);
}
*json = val;
}
/*
Saves json data to disk
*/
void Save();
CJson(const char* text, bool pathPredefined = false);
};

View File

@ -34,7 +34,7 @@ Locale::eReturnCodes Locale::Init(const char* path, const char* def, const char*
#endif #endif
for (auto& entry : std::filesystem::directory_iterator(m_path)) for (auto& entry : std::filesystem::directory_iterator(m_path))
{ {
if (entry.path().extension() == ".json") if (entry.path().extension() == ".toml")
{ {
std::string fileName = entry.path().stem().string(); std::string fileName = entry.path().stem().string();
#ifdef _GTA_ #ifdef _GTA_
@ -44,14 +44,14 @@ Locale::eReturnCodes Locale::Init(const char* path, const char* def, const char*
if (!strcmp(fallback, fileName.c_str())) if (!strcmp(fallback, fileName.c_str()))
{ {
std::string localePath = m_path + fileName + ".json"; std::string localePath = m_path + fileName;
if(m_pCallbackJson) if(m_pCallbackData)
{ {
delete m_pCallbackJson; delete m_pCallbackData;
m_pCallbackJson = nullptr; m_pCallbackData = nullptr;
} }
m_pCallbackJson = new CJson(localePath.c_str(), true); m_pCallbackData = new DataStore(localePath.c_str(), true);
} }
} }
} }
@ -113,12 +113,32 @@ Locale::eReturnCodes Locale::SetLocale(size_t index)
{ {
return eReturnCodes::INVALID_INDEX; return eReturnCodes::INVALID_INDEX;
} }
std::string localePath = m_path + m_locales[index];
std::string localeFile = m_locales[index]; m_pData = new DataStore(localePath.c_str(), true);
localeFile += ".json";
std::string localePath = m_path + localeFile;
m_pData = new CJson(localePath.c_str(), true);
localeIndex = index; localeIndex = index;
return eReturnCodes::SUCCESS; return eReturnCodes::SUCCESS;
} }
std::string Locale::GetText(std::string&& key, std::string&& defaultValue)
{
if (m_pData == nullptr)
{
return defaultValue;
}
// Return keyname if no default value is provided
if (defaultValue == "")
{
defaultValue = "#" + key;
}
std::string rtn = m_pData->Get(key.c_str(), defaultValue);
if (rtn == defaultValue)
{
return m_pCallbackData->Get(key.c_str(), defaultValue);
}
return rtn;
}

View File

@ -1,20 +1,20 @@
#pragma once #pragma once
#include <vector> #include <vector>
#include <string> #include <string>
#include "json.h" #include "datastore.h"
/* /*
A custom i18n library A custom i18n library
Loads strings from a json file Loads strings from a json file
Requires the CJson class Requires the DataStore class
*/ */
class Locale class Locale
{ {
private: private:
static inline std::vector<std::string> m_locales; static inline std::vector<std::string> m_locales;
static inline std::string m_path; static inline std::string m_path;
static inline CJson *m_pData = nullptr; static inline DataStore *m_pData = nullptr;
static inline CJson *m_pCallbackJson = nullptr; static inline DataStore *m_pCallbackData = nullptr;
static inline size_t localeIndex; static inline size_t localeIndex;
public: public:
@ -49,28 +49,7 @@ public:
You need to call SetLanguage once before calling this function You need to call SetLanguage once before calling this function
By default, the language is set to "en" By default, the language is set to "en"
*/ */
static inline std::string GetText(std::string&& key, std::string&& defaultValue = "") static std::string GetText(std::string&& key, std::string&& defaultValue = "");
{
if (m_pData == nullptr)
{
return defaultValue;
}
// Return keyname if no default value is provided
if (defaultValue == "")
{
defaultValue = "#" + key;
}
std::string rtn = m_pData->GetValueStr(key, defaultValue);
if (rtn == defaultValue)
{
return m_pCallbackJson->GetValueStr(key, defaultValue);
}
return rtn;
}
/* /*
Sets the language to use Sets the language to use

View File

@ -16,22 +16,22 @@ void Menu::Init()
{ {
// TODO: use structs // TODO: use structs
// Load config data // Load config data
m_Overlay::bCoord = gConfig.GetValue("overlay.coord", false); m_Overlay::bCoord = gConfig.Get("Overlay.ShowCoordinates", false);
m_Overlay::bCpuUsage = gConfig.GetValue("overlay.cpu_usage", false); m_Overlay::bCpuUsage = gConfig.Get("Overlay.ShowCPUUsage", false);
m_Overlay::bFPS = gConfig.GetValue("overlay.fps", false); m_Overlay::bFPS = gConfig.Get("Overlay.ShowFPS", false);
m_Overlay::bLocName = gConfig.GetValue("overlay.loc_name", false); m_Overlay::bLocName = gConfig.Get("Overlay.ShowLocationName", false);
m_Overlay::bTransparent = gConfig.GetValue("overlay.transparent", false); m_Overlay::bTransparent = gConfig.Get("Overlay.Transparent", false);
m_Overlay::bMemUsage = gConfig.GetValue("overlay.mem_usage", false); m_Overlay::bMemUsage = gConfig.Get("Overlay.ShowMemoryUsage", false);
m_Overlay::bVehHealth = gConfig.GetValue("overlay.veh_health", false); m_Overlay::bVehHealth = gConfig.Get("Overlay.ShowVehicleName", false);
m_Overlay::bVehSpeed = gConfig.GetValue("overlay.veh_speed", false); m_Overlay::bVehSpeed = gConfig.Get("Overlay.ShowVehicleSpeed", false);
m_Overlay::mSelectedPos = (DisplayPos)gConfig.GetValue("overlay.selected_pos", (int)DisplayPos::BOTTOM_RIGHT); m_Overlay::mSelectedPos = (DisplayPos)gConfig.Get("Overlay.SelectedPosition", (int)DisplayPos::BOTTOM_RIGHT);
m_Overlay::fPosX = gConfig.GetValue("overlay.pox", 0); m_Overlay::fPosX = gConfig.Get("Overlay.PosX", 0);
m_Overlay::fPosY = gConfig.GetValue("overlay.posy", 0); m_Overlay::fPosY = gConfig.Get("Overlay.PosY", 0);
m_Overlay::textColor[0] = gConfig.GetValue("overlay.text_color.r", 1.0f); m_Overlay::textColor[0] = gConfig.Get("Overlay.TextColor.Red", 1.0f);
m_Overlay::textColor[1] = gConfig.GetValue("overlay.text_color.g", 1.0f); m_Overlay::textColor[1] = gConfig.Get("Overlay.TextColor.Green", 1.0f);
m_Overlay::textColor[2] = gConfig.GetValue("overlay.text_color.b", 1.0f); m_Overlay::textColor[2] = gConfig.Get("Overlay.TextColor.Blue", 1.0f);
m_Overlay::textColor[3] = gConfig.GetValue("overlay.text_color.a", 1.0f); m_Overlay::textColor[3] = gConfig.Get("Overlay.TextColor.Alpha", 1.0f);
m_bDiscordRPC = gConfig.GetValue("menu.discord_rpc", false); m_bDiscordRPC = gConfig.Get("Menu.DiscordRPC", false);
Util::GetCPUUsageInit(); Util::GetCPUUsageInit();
MEMORYSTATUSEX memInfo; MEMORYSTATUSEX memInfo;
@ -63,8 +63,8 @@ void Menu::DrawOverlay()
{ {
if (m_Overlay::fPosX != NULL && m_Overlay::fPosY != NULL) if (m_Overlay::fPosX != NULL && m_Overlay::fPosY != NULL)
{ {
gConfig.SetValue("overlay.posx", m_Overlay::fPosX); gConfig.Set("Overlay.PosX", m_Overlay::fPosX);
gConfig.SetValue("overlay.posy", m_Overlay::fPosY); gConfig.Set("Overlay.PosY", m_Overlay::fPosY);
ImGui::SetNextWindowPos(ImVec2(m_Overlay::fPosX, m_Overlay::fPosY), ImGuiCond_Once); ImGui::SetNextWindowPos(ImVec2(m_Overlay::fPosX, m_Overlay::fPosY), ImGuiCond_Once);
} }
} }
@ -323,13 +323,7 @@ void Menu::ShowPage()
if (ImGui::BeginTabItem(TEXT("Menu.Config"))) if (ImGui::BeginTabItem(TEXT("Menu.Config")))
{ {
ImGui::Spacing(); ImGui::Spacing();
if (ImGui::Button(TEXT("Menu.ResetConfig"), ImVec2(Ui::GetSize(2)))) if (ImGui::Button(TEXT("Menu.ResetSize"), ImVec2(Ui::GetSize(1))))
{
gConfig.m_Data.clear();
SetHelpMessage(TEXT("Menu.ResetConfigMSG"));
}
ImGui::SameLine();
if (ImGui::Button(TEXT("Menu.ResetSize"), ImVec2(Ui::GetSize(2))))
{ {
CheatMenu::ResetMenuSize(); CheatMenu::ResetMenuSize();
} }
@ -366,7 +360,7 @@ void Menu::ShowPage()
{ {
RPC::Shutdown(); RPC::Shutdown();
} }
gConfig.SetValue("menu.discord_rpc", m_bDiscordRPC); gConfig.Set("Menu.DiscordRPC", m_bDiscordRPC);
} }
ImGui::NextColumn(); ImGui::NextColumn();
ImGui::Columns(1); ImGui::Columns(1);
@ -380,17 +374,17 @@ void Menu::ShowPage()
ImGui::SameLine(); ImGui::SameLine();
if (Ui::ListBox(TEXT("Menu.Position"), m_Overlay::posNames, (int&)m_Overlay::mSelectedPos)) if (Ui::ListBox(TEXT("Menu.Position"), m_Overlay::posNames, (int&)m_Overlay::mSelectedPos))
{ {
gConfig.SetValue("overlay.selected_pos", m_Overlay::mSelectedPos); gConfig.Set<int>("Overlay.SelectedPosition", static_cast<int>(m_Overlay::mSelectedPos));
} }
ImGui::Spacing(); ImGui::Spacing();
ImGui::SameLine(); ImGui::SameLine();
if (ImGui::ColorEdit4(TEXT("Menu.TextColor"), m_Overlay::textColor)) if (ImGui::ColorEdit4(TEXT("Menu.TextColor"), m_Overlay::textColor))
{ {
gConfig.SetValue("overlay.text_color.r", m_Overlay::textColor[0]); gConfig.Set("Overlay.TextColor.Red", m_Overlay::textColor[0]);
gConfig.SetValue("overlay.text_color.g", m_Overlay::textColor[1]); gConfig.Set("Overlay.TextColor.Green", m_Overlay::textColor[1]);
gConfig.SetValue("overlay.text_color.b", m_Overlay::textColor[2]); gConfig.Set("Overlay.TextColor.Blue", m_Overlay::textColor[2]);
gConfig.SetValue("overlay.text_color.a", m_Overlay::textColor[3]); gConfig.Set("Overlay.TextColor.Alpha", m_Overlay::textColor[3]);
} }
ImGui::Spacing(); ImGui::Spacing();
@ -398,44 +392,44 @@ void Menu::ShowPage()
ImGui::Columns(2, nullptr, false); ImGui::Columns(2, nullptr, false);
if (ImGui::Checkbox(TEXT("Menu.NoBG"), &m_Overlay::bTransparent)) if (ImGui::Checkbox(TEXT("Menu.NoBG"), &m_Overlay::bTransparent))
{ {
gConfig.SetValue("overlay.transparent", m_Overlay::bTransparent); gConfig.Set("Overlay.Transparent", m_Overlay::bTransparent);
} }
if (ImGui::Checkbox(TEXT("Menu.ShowCoords"), &m_Overlay::bCoord)) if (ImGui::Checkbox(TEXT("Menu.ShowCoords"), &m_Overlay::bCoord))
{ {
gConfig.SetValue("overlay.coord", m_Overlay::bCoord); gConfig.Set("Overlay.ShowCoordinates", m_Overlay::bCoord);
} }
if (ImGui::Checkbox(TEXT("Menu.ShowCPU"), &m_Overlay::bCpuUsage)) if (ImGui::Checkbox(TEXT("Menu.ShowCPU"), &m_Overlay::bCpuUsage))
{ {
gConfig.SetValue("overlay.cpu_usage", m_Overlay::bCpuUsage); gConfig.Set("Overlay.ShowCPUUsage", m_Overlay::bCpuUsage);
} }
if (ImGui::Checkbox(TEXT("Menu.ShowFPS"), &m_Overlay::bFPS)) if (ImGui::Checkbox(TEXT("Menu.ShowFPS"), &m_Overlay::bFPS))
{ {
gConfig.SetValue("overlay.fps", m_Overlay::bFPS); gConfig.Set("Overlay.ShowFPS", m_Overlay::bFPS);
} }
ImGui::NextColumn(); ImGui::NextColumn();
if (ImGui::Checkbox(TEXT("Menu.ShowLocation"), &m_Overlay::bLocName)) if (ImGui::Checkbox(TEXT("Menu.ShowLocation"), &m_Overlay::bLocName))
{ {
gConfig.SetValue("overlay.loc_name", m_Overlay::bLocName); gConfig.Set("Overlay.ShowLocationName", m_Overlay::bLocName);
} }
if (ImGui::Checkbox(TEXT("Menu.ShowRAM"), &m_Overlay::bMemUsage)) if (ImGui::Checkbox(TEXT("Menu.ShowRAM"), &m_Overlay::bMemUsage))
{ {
gConfig.SetValue("overlay.mem_usage", m_Overlay::bMemUsage); gConfig.Set("Overlay.ShowMemoryUsage", m_Overlay::bMemUsage);
} }
if (ImGui::Checkbox(TEXT("Menu.ShowVehHealth"), &m_Overlay::bVehHealth)) if (ImGui::Checkbox(TEXT("Menu.ShowVehHealth"), &m_Overlay::bVehHealth))
{ {
gConfig.SetValue("overlay.veh_health", m_Overlay::bVehHealth); gConfig.Set("Overlay.ShowVehicleHealth", m_Overlay::bVehHealth);
} }
if (ImGui::Checkbox(TEXT("Menu.ShowVehSpeed"), &m_Overlay::bVehSpeed)) if (ImGui::Checkbox(TEXT("Menu.ShowVehSpeed"), &m_Overlay::bVehSpeed))
{ {
gConfig.SetValue("overlay.veh_speed", m_Overlay::bVehSpeed); gConfig.Set("Overlay.ShowVehicleSpeed", m_Overlay::bVehSpeed);
} }
ImGui::Columns(1); ImGui::Columns(1);

View File

@ -1,6 +1,6 @@
#include "pch.h" #include "pch.h"
eRenderer gRenderer = Render_Unknown; eRenderer gRenderer = Render_Unknown;
CJson gConfig = CJson("config"); DataStore gConfig = DataStore(FILE_NAME, true);
Hotkey aimSkinChanger {VK_RETURN, VK_RETURN, "AimSkinChanger"}; Hotkey aimSkinChanger {VK_RETURN, VK_RETURN, "AimSkinChanger"};
Hotkey freeCam {VK_F6, VK_F6, "Freecam.Toggle"}; Hotkey freeCam {VK_F6, VK_F6, "Freecam.Toggle"};

View File

@ -57,7 +57,6 @@
#include "defines.h" #include "defines.h"
#include "log.h" #include "log.h"
#include "datastore.h" #include "datastore.h"
#include "json.h"
#include "hotkeys.h" #include "hotkeys.h"
#include "resourcestore.h" #include "resourcestore.h"
#include "fontmgr.h" #include "fontmgr.h"
@ -76,7 +75,7 @@ enum eRenderer
}; };
extern eRenderer gRenderer; extern eRenderer gRenderer;
extern CJson gConfig; extern DataStore gConfig;
// Fix function clashes // Fix function clashes
static void SetHelpMessage(const char *message, bool b1 = false, bool b2 = false, bool b3 = false) static void SetHelpMessage(const char *message, bool b1 = false, bool b2 = false, bool b3 = false)

View File

@ -52,9 +52,9 @@ private:
public: public:
#ifdef GTASA #ifdef GTASA
static inline DataStore m_SpecialPedData {"special_peds"}; static inline DataStore m_SpecialPedData {"special_peds"};
static inline ResourceStore m_PedData{"ped", eResourceType::TYPE_BOTH, ImVec2(65, 110)}; static inline ResourceStore m_PedData{"peds", eResourceType::TYPE_BOTH, ImVec2(65, 110)};
#else #else
static inline ResourceStore m_PedData {"ped", eResourceType::TYPE_TEXT}; static inline ResourceStore m_PedData {"peds", eResourceType::TYPE_TEXT};
#endif #endif
Ped() = delete; Ped() = delete;

View File

@ -88,7 +88,7 @@ void Player::Init()
#ifdef GTASA #ifdef GTASA
// Fix player model being broken after rebuild // Fix player model being broken after rebuild
patch::RedirectCall(0x5A834D, &PlayerModelBrokenFix); patch::RedirectCall(0x5A834D, &PlayerModelBrokenFix);
m_bAimSkinChanger = gConfig.GetValue("aim_skin_changer", false); m_bAimSkinChanger = gConfig.Get("aim_skin_changer", false);
#endif #endif
// Custom skins setup // Custom skins setup
@ -477,7 +477,7 @@ void Player::ShowPage()
Ui::CheckboxAddress(TEXT("Player.InfO2"), 0x96916E); Ui::CheckboxAddress(TEXT("Player.InfO2"), 0x96916E);
if (Ui::CheckboxBitFlag(TEXT("Player.InvisPlayer"), pPlayer->m_nPedFlags.bDontRender)) if (Ui::CheckboxBitFlag(TEXT("Player.InvisPlayer"), pPlayer->m_nPedFlags.bDontRender))
{ {
pPlayer->m_nPedFlags.bDontRender != pPlayer->m_nPedFlags.bDontRender; pPlayer->m_nPedFlags.bDontRender = !pPlayer->m_nPedFlags.bDontRender;
} }
Ui::CheckboxAddress(TEXT("Player.InfSprint"), 0xB7CEE4); Ui::CheckboxAddress(TEXT("Player.InfSprint"), 0xB7CEE4);
#else #else
@ -489,7 +489,7 @@ void Player::ShowPage()
#ifdef GTASA #ifdef GTASA
if (Ui::CheckboxBitFlag(TEXT("Player.LockControl"), pad->bPlayerSafe)) if (Ui::CheckboxBitFlag(TEXT("Player.LockControl"), pad->bPlayerSafe))
{ {
pad->bPlayerSafe != pad->bPlayerSafe; pad->bPlayerSafe = !pad->bPlayerSafe;
} }
Ui::CheckboxAddressEx(TEXT("Player.MaxAppeal"), 0x969180, 1, 0); Ui::CheckboxAddressEx(TEXT("Player.MaxAppeal"), 0x969180, 1, 0);
Ui::CheckboxAddress(TEXT("Player.MegaJump"), 0x96916C); Ui::CheckboxAddress(TEXT("Player.MegaJump"), 0x96916C);
@ -766,7 +766,7 @@ void Player::ShowPage()
if (Ui::CheckboxWithHint(TEXT("Player.AimSkinChanger"), &m_bAimSkinChanger, TEXT("Player.AimSkinChangerTip") + aimSkinChanger.Pressed())) if (Ui::CheckboxWithHint(TEXT("Player.AimSkinChanger"), &m_bAimSkinChanger, TEXT("Player.AimSkinChangerTip") + aimSkinChanger.Pressed()))
{ {
gConfig.SetValue("aim_skin_changer", m_bAimSkinChanger); gConfig.Set("aim_skin_changer", m_bAimSkinChanger);
} }
if (ImGui::BeginTabBar("AppearanceTabBar")) if (ImGui::BeginTabBar("AppearanceTabBar"))
{ {

View File

@ -35,7 +35,7 @@ void Teleport::FetchRadarSpriteData()
void Teleport::Init() void Teleport::Init()
{ {
m_bQuickTeleport = gConfig.GetValue("quick_teleport", false); m_bQuickTeleport = gConfig.Get("quick_teleport", false);
Events::processScriptsEvent += [] Events::processScriptsEvent += []
{ {
@ -219,7 +219,7 @@ void Teleport::ShowPage()
std::string(TEXT_S("Teleport.QuickTeleportHint") std::string(TEXT_S("Teleport.QuickTeleportHint")
+ quickTeleport.GetNameString()).c_str())) + quickTeleport.GetNameString()).c_str()))
{ {
gConfig.SetValue("quick_teleport", m_bQuickTeleport); gConfig.Set("quick_teleport", m_bQuickTeleport);
} }
#endif #endif
ImGui::Columns(1); ImGui::Columns(1);

View File

@ -37,7 +37,7 @@ void Updater::Process()
} }
const char* link = "https://api.github.com/repos/user-grinch/Cheat-Menu/tags"; const char* link = "https://api.github.com/repos/user-grinch/Cheat-Menu/tags";
char* path = PLUGIN_PATH((char*)"CheatMenu/json/versioninfo.json"); char* path = PLUGIN_PATH((char*)"CheatMenu/data/versioninfo.json");
HRESULT res = URLDownloadToFile(NULL, link, path, 0, NULL); HRESULT res = URLDownloadToFile(NULL, link, path, 0, NULL);
if (res == E_OUTOFMEMORY || res == INET_E_DOWNLOAD_FAILURE) if (res == E_OUTOFMEMORY || res == INET_E_DOWNLOAD_FAILURE)
@ -46,17 +46,26 @@ void Updater::Process()
return; return;
} }
CJson verinfo = CJson("versioninfo"); // Extract the version number
FILE *pFile= fopen(path, "r");
// fetch the version number if (pFile != NULL)
if (verinfo.m_Data.empty())
{ {
latestVer = MENU_VERSION_NUMBER; char buf[64];
} float version = 0.0f;
else while (fgets(buf, 64, pFile) != NULL)
{ {
latestVer = verinfo.m_Data.items().begin().value()["name"].get<std::string>(); sscanf(buf, "[{\"name\": \"%f\",", &version);
if (version != 0.0f)
{
std::stringstream ss;
ss << std::fixed << std::setprecision(2) << version;
latestVer = ss.str();
break;
}
}
fclose(pFile);
} }
remove(path);
if (latestVer > MENU_VERSION_NUMBER) if (latestVer > MENU_VERSION_NUMBER)
{ {