Set menu language to game language on first run (#1577)
* feat(translations): set menu language to game language on first run * fix(translations): add exception handlers * fix: more exception handlers
This commit is contained in:
parent
d1e839651b
commit
36d1dbeb22
@ -139,4 +139,6 @@ namespace big::functions
|
|||||||
using migrate_object = void (*)(CNetGamePlayer* player, rage::netObject* object, int type);
|
using migrate_object = void (*)(CNetGamePlayer* player, rage::netObject* object, int type);
|
||||||
|
|
||||||
using handle_chat_message = void (*)(void* chat_data, void*, rage::rlGamerHandle* handle, const char* text, bool is_team);
|
using handle_chat_message = void (*)(void* chat_data, void*, rage::rlGamerHandle* handle, const char* text, bool is_team);
|
||||||
|
|
||||||
|
using update_language = void (*)(bool);
|
||||||
}
|
}
|
||||||
|
@ -260,6 +260,9 @@ namespace big
|
|||||||
PVOID m_netfilter_handle_message{};
|
PVOID m_netfilter_handle_message{};
|
||||||
|
|
||||||
functions::handle_chat_message m_handle_chat_message{};
|
functions::handle_chat_message m_handle_chat_message{};
|
||||||
|
|
||||||
|
int* m_language;
|
||||||
|
functions::update_language m_update_language{};
|
||||||
};
|
};
|
||||||
#pragma pack(pop)
|
#pragma pack(pop)
|
||||||
static_assert(sizeof(gta_pointers) % 8 == 0, "Pointers are not properly aligned");
|
static_assert(sizeof(gta_pointers) % 8 == 0, "Pointers are not properly aligned");
|
||||||
|
@ -66,9 +66,6 @@ BOOL APIENTRY DllMain(HMODULE hmod, DWORD reason, PVOID)
|
|||||||
LOG(INFO) << "Yim's Menu Initializing";
|
LOG(INFO) << "Yim's Menu Initializing";
|
||||||
LOGF(INFO, "Git Info\n\tBranch:\t{}\n\tHash:\t{}\n\tDate:\t{}", version::GIT_BRANCH, version::GIT_SHA1, version::GIT_DATE);
|
LOGF(INFO, "Git Info\n\tBranch:\t{}\n\tHash:\t{}\n\tDate:\t{}", version::GIT_BRANCH, version::GIT_SHA1, version::GIT_DATE);
|
||||||
|
|
||||||
g_translation_service.init();
|
|
||||||
LOG(INFO) << "Translation Service initialized.";
|
|
||||||
|
|
||||||
auto thread_pool_instance = std::make_unique<thread_pool>();
|
auto thread_pool_instance = std::make_unique<thread_pool>();
|
||||||
LOG(INFO) << "Thread pool initialized.";
|
LOG(INFO) << "Thread pool initialized.";
|
||||||
|
|
||||||
@ -88,6 +85,9 @@ BOOL APIENTRY DllMain(HMODULE hmod, DWORD reason, PVOID)
|
|||||||
auto fiber_pool_instance = std::make_unique<fiber_pool>(11);
|
auto fiber_pool_instance = std::make_unique<fiber_pool>(11);
|
||||||
LOG(INFO) << "Fiber pool initialized.";
|
LOG(INFO) << "Fiber pool initialized.";
|
||||||
|
|
||||||
|
g_translation_service.init();
|
||||||
|
LOG(INFO) << "Translation Service initialized.";
|
||||||
|
|
||||||
auto hooking_instance = std::make_unique<hooking>();
|
auto hooking_instance = std::make_unique<hooking>();
|
||||||
LOG(INFO) << "Hooking initialized.";
|
LOG(INFO) << "Hooking initialized.";
|
||||||
|
|
||||||
|
@ -1213,6 +1213,16 @@ namespace big
|
|||||||
g_pointers->m_gta.m_handle_chat_message = ptr.as<functions::handle_chat_message>();
|
g_pointers->m_gta.m_handle_chat_message = ptr.as<functions::handle_chat_message>();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
// Language & Update Language
|
||||||
|
{
|
||||||
|
"L&UL",
|
||||||
|
"83 3D ? ? ? ? ? 44 8B C3",
|
||||||
|
[](memory::handle ptr)
|
||||||
|
{
|
||||||
|
g_pointers->m_gta.m_language = ptr.add(2).rip().add(1).as<int*>();
|
||||||
|
g_pointers->m_gta.m_update_language = ptr.add(0x38).rip().as<functions::update_language>();
|
||||||
|
}
|
||||||
|
},
|
||||||
// Max Wanted Level
|
// Max Wanted Level
|
||||||
{
|
{
|
||||||
"MWL",
|
"MWL",
|
||||||
|
@ -22,11 +22,19 @@ namespace big
|
|||||||
|
|
||||||
if (response.status_code == 200)
|
if (response.status_code == 200)
|
||||||
{
|
{
|
||||||
nlohmann::json obj = nlohmann::json::parse(response.text);
|
try
|
||||||
if (obj["Total"] > 0 && username.compare(obj["Accounts"].at(0)["Nickname"]) == 0)
|
|
||||||
{
|
{
|
||||||
result = obj["Accounts"].at(0)["RockstarId"];
|
nlohmann::json obj = nlohmann::json::parse(response.text);
|
||||||
return true;
|
|
||||||
|
if (obj["Total"] > 0 && username.compare(obj["Accounts"].at(0)["Nickname"]) == 0)
|
||||||
|
{
|
||||||
|
result = obj["Accounts"].at(0)["RockstarId"];
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (std::exception& e)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -39,9 +47,16 @@ namespace big
|
|||||||
|
|
||||||
if (response.status_code == 200)
|
if (response.status_code == 200)
|
||||||
{
|
{
|
||||||
nlohmann::json obj = nlohmann::json::parse(response.text);
|
try
|
||||||
result = obj["Accounts"].at(0)["RockstarAccount"]["Name"];
|
{
|
||||||
return true;
|
nlohmann::json obj = nlohmann::json::parse(response.text);
|
||||||
|
result = obj["Accounts"].at(0)["RockstarAccount"]["Name"];
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
catch (std::exception& e)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
@ -61,9 +76,18 @@ namespace big
|
|||||||
cpr::Header{{"X-AMC", "true"}, {"X-Requested-With", "XMLHttpRequest"}},
|
cpr::Header{{"X-AMC", "true"}, {"X-Requested-With", "XMLHttpRequest"}},
|
||||||
cpr::Parameters{{"title", "gtav"}, {"contentId", content_id.data()}});
|
cpr::Parameters{{"title", "gtav"}, {"contentId", content_id.data()}});
|
||||||
|
|
||||||
result = nlohmann::json::parse(response.text);
|
if (response.status_code != 200)
|
||||||
|
return false;
|
||||||
|
|
||||||
return response.status_code == 200;
|
try
|
||||||
|
{
|
||||||
|
result = nlohmann::json::parse(response.text);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
catch (std::exception& e)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool api_service::download_job_metadata(std::string_view content_id, int f1, int f0, int lang)
|
bool api_service::download_job_metadata(std::string_view content_id, int f1, int f0, int lang)
|
||||||
|
@ -147,7 +147,6 @@ namespace big
|
|||||||
{tabs::HOTKEY_SETTINGS, {"GUI_TAB_HOTKEYS", view::hotkey_settings}},
|
{tabs::HOTKEY_SETTINGS, {"GUI_TAB_HOTKEYS", view::hotkey_settings}},
|
||||||
{tabs::REACTION_SETTINGS, {"GUI_TAB_REACTIONS", view::reaction_settings}},
|
{tabs::REACTION_SETTINGS, {"GUI_TAB_REACTIONS", view::reaction_settings}},
|
||||||
{tabs::PROTECTION_SETTINGS, {"GUI_TAB_PROTECTION", view::protection_settings}},
|
{tabs::PROTECTION_SETTINGS, {"GUI_TAB_PROTECTION", view::protection_settings}},
|
||||||
{tabs::TRANSLATION_SETTINGS, {"GUI_TAB_TRANSLATION", view::translation_settings}},
|
|
||||||
{tabs::DEBUG, {"GUI_TAB_DEBUG", nullptr}},
|
{tabs::DEBUG, {"GUI_TAB_DEBUG", nullptr}},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -40,20 +40,27 @@ namespace big
|
|||||||
m_selected = nullptr;
|
m_selected = nullptr;
|
||||||
if (std::filesystem::exists(m_file_path))
|
if (std::filesystem::exists(m_file_path))
|
||||||
{
|
{
|
||||||
std::ifstream file_stream(m_file_path);
|
try
|
||||||
|
|
||||||
nlohmann::json json;
|
|
||||||
file_stream >> json;
|
|
||||||
file_stream.close();
|
|
||||||
|
|
||||||
for (auto& [key, value] : json.items())
|
|
||||||
{
|
{
|
||||||
auto player = value.get<std::shared_ptr<persistent_player>>();
|
std::ifstream file_stream(m_file_path);
|
||||||
m_players[std::stoll(key)] = player;
|
|
||||||
|
|
||||||
std::string lower = player->name;
|
nlohmann::json json;
|
||||||
std::transform(lower.begin(), lower.end(), lower.begin(), ::tolower);
|
file_stream >> json;
|
||||||
m_sorted_players[lower] = player;
|
file_stream.close();
|
||||||
|
|
||||||
|
for (auto& [key, value] : json.items())
|
||||||
|
{
|
||||||
|
auto player = value.get<std::shared_ptr<persistent_player>>();
|
||||||
|
m_players[std::stoll(key)] = player;
|
||||||
|
|
||||||
|
std::string lower = player->name;
|
||||||
|
std::transform(lower.begin(), lower.end(), lower.begin(), ::tolower);
|
||||||
|
m_sorted_players[lower] = player;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (std::exception& e)
|
||||||
|
{
|
||||||
|
LOG(WARNING) << "Failed to load player database file. " << e.what();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -195,7 +202,8 @@ namespace big
|
|||||||
{
|
{
|
||||||
if (it->second->online_state == PlayerOnlineStatus::OFFLINE && it->second->notify_online)
|
if (it->second->online_state == PlayerOnlineStatus::OFFLINE && it->second->notify_online)
|
||||||
{
|
{
|
||||||
g_notification_service->push_success("Player DB", std::format("{} is now online!", it->second->name));
|
g_notification_service->push_success("Player DB",
|
||||||
|
std::format("{} is now online!", it->second->name));
|
||||||
}
|
}
|
||||||
it->second->online_state = PlayerOnlineStatus::ONLINE;
|
it->second->online_state = PlayerOnlineStatus::ONLINE;
|
||||||
|
|
||||||
|
@ -10,8 +10,9 @@ namespace big
|
|||||||
std::string selected_language;
|
std::string selected_language;
|
||||||
std::string fallback_default_language;
|
std::string fallback_default_language;
|
||||||
std::map<std::string, translation_entry> fallback_languages;
|
std::map<std::string, translation_entry> fallback_languages;
|
||||||
|
bool default_language_set = false;
|
||||||
|
|
||||||
NLOHMANN_DEFINE_TYPE_INTRUSIVE(local_index, version, selected_language, fallback_default_language, fallback_languages)
|
NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(local_index, version, selected_language, fallback_default_language, fallback_languages, default_language_set)
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
@ -1,6 +1,8 @@
|
|||||||
#include "translation_service.hpp"
|
#include "translation_service.hpp"
|
||||||
|
|
||||||
|
#include "fiber_pool.hpp"
|
||||||
#include "file_manager.hpp"
|
#include "file_manager.hpp"
|
||||||
|
#include "pointers.hpp"
|
||||||
#include "thread_pool.hpp"
|
#include "thread_pool.hpp"
|
||||||
|
|
||||||
#include <cpr/cpr.h>
|
#include <cpr/cpr.h>
|
||||||
@ -39,7 +41,12 @@ namespace big
|
|||||||
update_language_packs();
|
update_language_packs();
|
||||||
m_local_index.version = m_remote_index.version;
|
m_local_index.version = m_remote_index.version;
|
||||||
}
|
}
|
||||||
|
|
||||||
load_translations();
|
load_translations();
|
||||||
|
|
||||||
|
if (loaded_remote_index)
|
||||||
|
try_set_default_language();
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -56,6 +63,7 @@ namespace big
|
|||||||
m_local_index.version = m_remote_index.version;
|
m_local_index.version = m_remote_index.version;
|
||||||
|
|
||||||
load_translations();
|
load_translations();
|
||||||
|
try_set_default_language();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string_view translation_service::get_translation(const std::string_view translation_key) const
|
std::string_view translation_service::get_translation(const std::string_view translation_key) const
|
||||||
@ -130,6 +138,18 @@ namespace big
|
|||||||
save_local_index();
|
save_local_index();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool translation_service::does_language_exist(const std::string_view language)
|
||||||
|
{
|
||||||
|
auto file = m_translation_directory->get_file(std::format("./{}.json", language));
|
||||||
|
if (file.exists())
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if (auto it = m_remote_index.translations.find(language.data()); it != m_remote_index.translations.end())
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
nlohmann::json translation_service::load_translation(const std::string_view pack_id)
|
nlohmann::json translation_service::load_translation(const std::string_view pack_id)
|
||||||
{
|
{
|
||||||
auto file = m_translation_directory->get_file(std::format("./{}.json", pack_id));
|
auto file = m_translation_directory->get_file(std::format("./{}.json", pack_id));
|
||||||
@ -144,7 +164,20 @@ namespace big
|
|||||||
// make a copy available
|
// make a copy available
|
||||||
m_local_index.fallback_languages[pack_id.data()] = m_remote_index.translations[pack_id.data()];
|
m_local_index.fallback_languages[pack_id.data()] = m_remote_index.translations[pack_id.data()];
|
||||||
}
|
}
|
||||||
return nlohmann::json::parse(std::ifstream(file.get_path(), std::ios::binary));
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return nlohmann::json::parse(std::ifstream(file.get_path(), std::ios::binary));
|
||||||
|
}
|
||||||
|
catch (std::exception& e)
|
||||||
|
{
|
||||||
|
LOG(WARNING) << "Failed to parse language pack. " << e.what();
|
||||||
|
|
||||||
|
if (auto it = m_remote_index.translations.find(pack_id.data()); it != m_remote_index.translations.end()) // ensure that local language files are not removed
|
||||||
|
std::filesystem::remove(file.get_path());
|
||||||
|
|
||||||
|
return {};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool translation_service::download_language_pack(const std::string_view pack_id)
|
bool translation_service::download_language_pack(const std::string_view pack_id)
|
||||||
@ -155,12 +188,20 @@ namespace big
|
|||||||
|
|
||||||
if (response.status_code == 200)
|
if (response.status_code == 200)
|
||||||
{
|
{
|
||||||
auto json = nlohmann::json::parse(response.text);
|
try
|
||||||
auto lang_file = m_translation_directory->get_file("./" + it->second.file);
|
{
|
||||||
|
auto json = nlohmann::json::parse(response.text);
|
||||||
|
auto lang_file = m_translation_directory->get_file("./" + it->second.file);
|
||||||
|
|
||||||
auto out_file = std::ofstream(lang_file.get_path(), std::ios::binary | std::ios::trunc);
|
auto out_file = std::ofstream(lang_file.get_path(), std::ios::binary | std::ios::trunc);
|
||||||
out_file << json.dump(4);
|
out_file << json.dump(4);
|
||||||
out_file.close();
|
out_file.close();
|
||||||
|
}
|
||||||
|
catch (std::exception& e)
|
||||||
|
{
|
||||||
|
LOG(WARNING) << "Failed to parse language pack. " << e.what();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -174,7 +215,15 @@ namespace big
|
|||||||
|
|
||||||
if (response.status_code == 200)
|
if (response.status_code == 200)
|
||||||
{
|
{
|
||||||
m_remote_index = nlohmann::json::parse(response.text);
|
try
|
||||||
|
{
|
||||||
|
m_remote_index = nlohmann::json::parse(response.text);
|
||||||
|
}
|
||||||
|
catch (std::exception& e)
|
||||||
|
{
|
||||||
|
LOG(WARNING) << "Failed to load remote index. " << e.what();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -186,8 +235,16 @@ namespace big
|
|||||||
const auto local_index = m_translation_directory->get_file("./index.json");
|
const auto local_index = m_translation_directory->get_file("./index.json");
|
||||||
if (local_index.exists())
|
if (local_index.exists())
|
||||||
{
|
{
|
||||||
const auto path = local_index.get_path();
|
try
|
||||||
m_local_index = nlohmann::json::parse(std::ifstream(path, std::ios::binary));
|
{
|
||||||
|
const auto path = local_index.get_path();
|
||||||
|
m_local_index = nlohmann::json::parse(std::ifstream(path, std::ios::binary));
|
||||||
|
}
|
||||||
|
catch (std::exception& e)
|
||||||
|
{
|
||||||
|
LOG(WARNING) << "Failed to load local index. " << e.what();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -220,4 +277,40 @@ namespace big
|
|||||||
|
|
||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void translation_service::try_set_default_language()
|
||||||
|
{
|
||||||
|
if (!m_local_index.default_language_set)
|
||||||
|
{
|
||||||
|
g_fiber_pool->queue_job([this] {
|
||||||
|
std::string preferred_lang = "en_US";
|
||||||
|
auto game_lang = *g_pointers->m_gta.m_language;
|
||||||
|
|
||||||
|
switch (game_lang)
|
||||||
|
{
|
||||||
|
case 1: preferred_lang = "fr_FR"; break;
|
||||||
|
case 2: preferred_lang = "de_DE"; break;
|
||||||
|
case 3: preferred_lang = "it_IT"; break;
|
||||||
|
case 4:
|
||||||
|
case 11: preferred_lang = "es_ES"; break;
|
||||||
|
case 5: preferred_lang = "pt_BR"; break;
|
||||||
|
case 6: preferred_lang = "pl_PL"; break;
|
||||||
|
case 7: preferred_lang = "ru_RU"; break;
|
||||||
|
case 8: preferred_lang = "ko_KR"; break;
|
||||||
|
case 9: preferred_lang = "zh_TW"; break;
|
||||||
|
case 10: preferred_lang = "ja_JP"; break;
|
||||||
|
case 12: preferred_lang = "zh_CN"; break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (does_language_exist(preferred_lang))
|
||||||
|
{
|
||||||
|
m_local_index.selected_language = preferred_lang;
|
||||||
|
save_local_index();
|
||||||
|
}
|
||||||
|
|
||||||
|
m_local_index.default_language_set = true;
|
||||||
|
load_translations();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -23,7 +23,7 @@ namespace big
|
|||||||
void init();
|
void init();
|
||||||
|
|
||||||
std::string_view get_translation(const std::string_view translation_key) const;
|
std::string_view get_translation(const std::string_view translation_key) const;
|
||||||
std::string_view get_translation(const rage::joaat_t translation_key, const std::string_view fallback = { 0, 0 }) const;
|
std::string_view get_translation(const rage::joaat_t translation_key, const std::string_view fallback = {0, 0}) const;
|
||||||
|
|
||||||
std::map<std::string, translation_entry>& available_translations();
|
std::map<std::string, translation_entry>& available_translations();
|
||||||
const std::string& current_language_pack();
|
const std::string& current_language_pack();
|
||||||
@ -32,6 +32,7 @@ namespace big
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
void load_translations();
|
void load_translations();
|
||||||
|
bool does_language_exist(const std::string_view language);
|
||||||
nlohmann::json load_translation(const std::string_view pack_id);
|
nlohmann::json load_translation(const std::string_view pack_id);
|
||||||
|
|
||||||
bool download_language_pack(const std::string_view pack_id);
|
bool download_language_pack(const std::string_view pack_id);
|
||||||
@ -51,6 +52,8 @@ namespace big
|
|||||||
void use_fallback_remote();
|
void use_fallback_remote();
|
||||||
cpr::Response download_file(const std::string& filename);
|
cpr::Response download_file(const std::string& filename);
|
||||||
|
|
||||||
|
void try_set_default_language();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const std::string m_url;
|
const std::string m_url;
|
||||||
const std::string m_fallback_url;
|
const std::string m_fallback_url;
|
||||||
|
@ -30,14 +30,21 @@ namespace big
|
|||||||
auto file_path = item.path();
|
auto file_path = item.path();
|
||||||
if (file_path.extension() == ".json")
|
if (file_path.extension() == ".json")
|
||||||
{
|
{
|
||||||
auto profile_file = std::ifstream(file_path, std::ios::binary);
|
try
|
||||||
nlohmann::json j;
|
{
|
||||||
profile_file >> j;
|
auto profile_file = std::ifstream(file_path, std::ios::binary);
|
||||||
profile_file.close();
|
nlohmann::json j;
|
||||||
|
profile_file >> j;
|
||||||
|
profile_file.close();
|
||||||
|
|
||||||
m_handling_profiles.emplace(file_path.stem().string(), j.get<handling_profile>());
|
m_handling_profiles.emplace(file_path.stem().string(), j.get<handling_profile>());
|
||||||
|
|
||||||
++files_loaded;
|
++files_loaded;
|
||||||
|
}
|
||||||
|
catch (std::exception& e)
|
||||||
|
{
|
||||||
|
LOG(WARNING) << "Failed to load " << file_path.filename() << ". " << e.what();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// deprecate this
|
// deprecate this
|
||||||
else if (file_path.extension() == ".bin")
|
else if (file_path.extension() == ".bin")
|
||||||
@ -46,7 +53,7 @@ namespace big
|
|||||||
|
|
||||||
auto profile_file = std::ifstream(file_path, std::ios::binary);
|
auto profile_file = std::ifstream(file_path, std::ios::binary);
|
||||||
auto profile = handling_profile();
|
auto profile = handling_profile();
|
||||||
profile_file.read(reinterpret_cast<char*>(&profile), 328);// hardcoded old size to prevent overreading
|
profile_file.read(reinterpret_cast<char*>(&profile), 328); // hardcoded old size to prevent overreading
|
||||||
profile_file.close();
|
profile_file.close();
|
||||||
|
|
||||||
const auto new_save = file_path.stem().string();
|
const auto new_save = file_path.stem().string();
|
||||||
|
@ -35,8 +35,16 @@ namespace big
|
|||||||
|
|
||||||
nlohmann::json vehicle_json;
|
nlohmann::json vehicle_json;
|
||||||
|
|
||||||
file_stream >> vehicle_json;
|
try
|
||||||
file_stream.close();
|
{
|
||||||
|
file_stream >> vehicle_json;
|
||||||
|
file_stream.close();
|
||||||
|
}
|
||||||
|
catch (std::exception& e)
|
||||||
|
{
|
||||||
|
g_notification_service->push_warning("PERSIST_CAR_TITLE"_T.data(), "Failed to load JSON file");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
return spawn_vehicle_full(vehicle_json, self::ped);
|
return spawn_vehicle_full(vehicle_json, self::ped);
|
||||||
}
|
}
|
||||||
|
@ -1,9 +1,63 @@
|
|||||||
|
#include "core/data/language_codes.hpp"
|
||||||
|
#include "pointers.hpp"
|
||||||
|
#include "thread_pool.hpp"
|
||||||
#include "views/view.hpp"
|
#include "views/view.hpp"
|
||||||
|
|
||||||
namespace big
|
namespace big
|
||||||
{
|
{
|
||||||
void view::settings()
|
void view::settings()
|
||||||
{
|
{
|
||||||
|
const auto& language_entries = g_translation_service.available_translations();
|
||||||
|
const auto& current_pack = g_translation_service.current_language_pack();
|
||||||
|
|
||||||
|
ImGui::SeparatorText("SETTINGS_LANGUAGES"_T.data());
|
||||||
|
|
||||||
|
if (ImGui::BeginCombo("Menu Language", language_entries.at(current_pack).name.c_str()))
|
||||||
|
{
|
||||||
|
for (auto& i : language_entries)
|
||||||
|
{
|
||||||
|
if (ImGui::Selectable(i.second.name.c_str(), i.first == current_pack))
|
||||||
|
g_translation_service.select_language_pack(i.first);
|
||||||
|
|
||||||
|
if (i.first == current_pack)
|
||||||
|
{
|
||||||
|
ImGui::SetItemDefaultFocus();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ImGui::EndCombo();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ImGui::BeginCombo("Game Language", languages[*g_pointers->m_gta.m_language].name))
|
||||||
|
{
|
||||||
|
for (auto& language : languages)
|
||||||
|
{
|
||||||
|
if (ImGui::Selectable(language.name, language.id == *g_pointers->m_gta.m_language))
|
||||||
|
{
|
||||||
|
*g_pointers->m_gta.m_language = language.id;
|
||||||
|
|
||||||
|
g_fiber_pool->queue_job([] {
|
||||||
|
g_pointers->m_gta.m_update_language(true);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (language.id == *g_pointers->m_gta.m_language)
|
||||||
|
{
|
||||||
|
ImGui::SetItemDefaultFocus();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui::EndCombo();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (components::button("Force Update Languages"))
|
||||||
|
{
|
||||||
|
g_thread_pool->push([] {
|
||||||
|
g_translation_service.update_language_packs();
|
||||||
|
|
||||||
|
g_notification_service->push_success("Translations", "Finished updating translations.");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
ImGui::SeparatorText("SETTINGS_MISC"_T.data());
|
ImGui::SeparatorText("SETTINGS_MISC"_T.data());
|
||||||
ImGui::Checkbox("SETTINGS_MISC_DEV_DLC"_T.data(), &g.settings.dev_dlc);
|
ImGui::Checkbox("SETTINGS_MISC_DEV_DLC"_T.data(), &g.settings.dev_dlc);
|
||||||
|
|
||||||
|
@ -1,37 +0,0 @@
|
|||||||
#include "thread_pool.hpp"
|
|
||||||
#include "views/view.hpp"
|
|
||||||
|
|
||||||
|
|
||||||
namespace big
|
|
||||||
{
|
|
||||||
void view::translation_settings()
|
|
||||||
{
|
|
||||||
const auto& language_entries = g_translation_service.available_translations();
|
|
||||||
const auto current_pack = g_translation_service.current_language_pack();
|
|
||||||
|
|
||||||
ImGui::Text("SETTINGS_LANGUAGES"_T.data());
|
|
||||||
if (ImGui::BeginCombo("##combo-languages", language_entries.at(current_pack).name.c_str()))
|
|
||||||
{
|
|
||||||
for (auto& i : language_entries)
|
|
||||||
{
|
|
||||||
if (ImGui::Selectable(i.second.name.c_str(), i.first == current_pack))
|
|
||||||
g_translation_service.select_language_pack(i.first);
|
|
||||||
|
|
||||||
if (i.first == current_pack)
|
|
||||||
{
|
|
||||||
ImGui::SetItemDefaultFocus();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ImGui::EndCombo();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (components::button("Force Update Languages"))
|
|
||||||
{
|
|
||||||
g_thread_pool->push([] {
|
|
||||||
g_translation_service.update_language_packs();
|
|
||||||
|
|
||||||
g_notification_service->push_success("Translations", "Finished updating translations.");
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -24,7 +24,6 @@ namespace big
|
|||||||
public:
|
public:
|
||||||
static void active_view();
|
static void active_view();
|
||||||
static void esp_settings();
|
static void esp_settings();
|
||||||
static void context_menu_settings();
|
|
||||||
static void outfit_editor();
|
static void outfit_editor();
|
||||||
static void outfit_slots();
|
static void outfit_slots();
|
||||||
static void stat_editor();
|
static void stat_editor();
|
||||||
@ -34,7 +33,6 @@ namespace big
|
|||||||
static void handling_saved_profiles();
|
static void handling_saved_profiles();
|
||||||
static void reaction_settings();
|
static void reaction_settings();
|
||||||
static void protection_settings();
|
static void protection_settings();
|
||||||
static void translation_settings();
|
|
||||||
static void heading();
|
static void heading();
|
||||||
static void mobile();
|
static void mobile();
|
||||||
static void navigation();
|
static void navigation();
|
||||||
|
@ -75,7 +75,7 @@ namespace big
|
|||||||
components::button("CREATOR_JOB_IMPORT"_T, [] {
|
components::button("CREATOR_JOB_IMPORT"_T, [] {
|
||||||
g_thread_pool->push([] {
|
g_thread_pool->push([] {
|
||||||
std::string content_id = job_link;
|
std::string content_id = job_link;
|
||||||
nlohmann::json job_details;
|
|
||||||
if (content_id.starts_with("https://"))
|
if (content_id.starts_with("https://"))
|
||||||
content_id = content_id.substr(46);
|
content_id = content_id.substr(46);
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user