General code and GUI cleanup (#1200)
* feat(native_hooks): removed useless bail kick hook * feat(Translations): add button to force update languages * refactor: reorganize GUI for world * refactor: improve exception handler Modified the exception handler to not catch C++ try/catch blocks before those could gracefully catch the error. * chore: debug removed crash test button * chore: removed script exception handler * feat(OrbitalDrone): add translations * feat(VehicleController): add translation keys * feat: added player admin detected translation keys * feat(Views): add cache sub menu
This commit is contained in:
@ -11,6 +11,8 @@ namespace big
|
||||
WEAPONS,
|
||||
TELEPORT,
|
||||
MOBILE,
|
||||
OUTFIT_EDITOR,
|
||||
OUTFIT_SLOTS,
|
||||
|
||||
VEHICLE,
|
||||
HANDLING,
|
||||
@ -26,10 +28,8 @@ namespace big
|
||||
|
||||
WORLD,
|
||||
SPAWN_PED,
|
||||
TIME_AND_WEATHER,
|
||||
CREATOR,
|
||||
TRAIN,
|
||||
WATER,
|
||||
BLACKHOLE,
|
||||
MODEL_SWAPPER,
|
||||
NEARBY,
|
||||
@ -41,13 +41,12 @@ namespace big
|
||||
SPOOFING,
|
||||
PLAYER_DATABASE,
|
||||
SESSION_BROWSER,
|
||||
STAT_EDITOR,
|
||||
|
||||
SETTINGS,
|
||||
OUTFIT_EDITOR,
|
||||
OUTFIT_SLOTS,
|
||||
STAT_EDITOR,
|
||||
CONTEXT_MENU_SETTINGS,
|
||||
ESP_SETTINGS,
|
||||
GTA_CACHE_SETTINGS,
|
||||
GUI_SETTINGS,
|
||||
HOTKEY_SETTINGS,
|
||||
REACTION_SETTINGS,
|
||||
@ -80,6 +79,8 @@ namespace big
|
||||
{tabs::WEAPONS, {"GUI_TAB_WEAPONS", view::weapons}},
|
||||
{tabs::MOBILE, {"GUI_TAB_MOBILE", view::mobile}},
|
||||
{tabs::TELEPORT, {"GUI_TAB_TELEPORT", view::teleport}},
|
||||
{tabs::OUTFIT_EDITOR, {"GUI_TAB_OUTFIT_EDITOR", view::outfit_editor}},
|
||||
{tabs::OUTFIT_SLOTS, {"GUI_TAB_OUTFIT_SLOTS", view::outfit_slots}},
|
||||
},
|
||||
},
|
||||
},
|
||||
@ -112,17 +113,15 @@ namespace big
|
||||
tabs::WORLD,
|
||||
{
|
||||
"GUI_TAB_WORLD",
|
||||
nullptr,
|
||||
view::world,
|
||||
{
|
||||
{tabs::SPAWN_PED, {"GUI_TAB_SPAWN_PED", view::spawn_ped}},
|
||||
{tabs::TIME_AND_WEATHER, {"GUI_TAB_TIME_N_WEATHER", view::time_and_weather}},
|
||||
{tabs::CREATOR, {"GUI_TAB_CREATOR", view::creator}},
|
||||
{tabs::TRAIN, {"GUI_TAB_TRAIN", view::train}},
|
||||
{tabs::WATER, {"GUI_TAB_WATER", view::water}},
|
||||
{tabs::BLACKHOLE, {"GUI_TAB_BLACKHOLE", view::blackhole}},
|
||||
{tabs::MODEL_SWAPPER, {"GUI_TAB_MODEL_SWAPPER", view::model_swapper}},
|
||||
{tabs::NEARBY, {"GUI_TAB_NEARBY", view::nearby}},
|
||||
{tabs::ORBITAL_DRONE, {"Orbital Drone", view::orbital_drone}},
|
||||
{tabs::ORBITAL_DRONE, {"GUI_TAB_ORBITAL_DRONE", view::orbital_drone}},
|
||||
},
|
||||
},
|
||||
},
|
||||
@ -137,6 +136,7 @@ namespace big
|
||||
{tabs::MISSIONS, {"GUI_TAB_MISSIONS", view::missions}},
|
||||
{tabs::PLAYER_DATABASE, {"GUI_TAB_PLAYER_DB", view::player_database}},
|
||||
{tabs::SESSION_BROWSER, {"GUI_TAB_SESSION_BROWSER", view::session_browser}},
|
||||
{tabs::STAT_EDITOR, {"GUI_TAB_STAT_EDITOR", view::stat_editor}},
|
||||
},
|
||||
},
|
||||
},
|
||||
@ -146,11 +146,9 @@ namespace big
|
||||
"GUI_TAB_SETTINGS",
|
||||
view::settings,
|
||||
{
|
||||
{tabs::OUTFIT_EDITOR, {"GUI_TAB_OUTFIT_EDITOR", view::outfit_editor}},
|
||||
{tabs::OUTFIT_SLOTS, {"GUI_TAB_OUTFIT_SLOTS", view::outfit_slots}},
|
||||
{tabs::STAT_EDITOR, {"GUI_TAB_STAT_EDITOR", view::stat_editor}},
|
||||
{tabs::CONTEXT_MENU_SETTINGS, {"GUI_TAB_CONTEXT_MENU", view::context_menu_settings}},
|
||||
{tabs::ESP_SETTINGS, {"GUI_TAB_ESP", view::esp_settings}},
|
||||
{tabs::GTA_CACHE_SETTINGS, {"GTA Cache", view::gta_cache}},
|
||||
{tabs::GUI_SETTINGS, {"GUI_TAB_GUI", view::gui_settings}},
|
||||
{tabs::HOTKEY_SETTINGS, {"GUI_TAB_HOTKEYS", view::hotkey_settings}},
|
||||
{tabs::REACTION_SETTINGS, {"GUI_TAB_REACTIONS", view::reaction_settings}},
|
||||
|
@ -1,213 +1,213 @@
|
||||
#include "translation_service.hpp"
|
||||
|
||||
#include "file_manager.hpp"
|
||||
#include "thread_pool.hpp"
|
||||
|
||||
#include <cpr/cpr.h>
|
||||
|
||||
namespace big
|
||||
{
|
||||
translation_service::translation_service() :
|
||||
m_url("https://cdn.jsdelivr.net/gh/YimMenu/Translations@master")
|
||||
{
|
||||
}
|
||||
|
||||
void translation_service::init()
|
||||
{
|
||||
m_translation_directory = std::make_unique<folder>(g_file_manager->get_project_folder("./translations").get_path());
|
||||
|
||||
bool loaded_remote_index = false;
|
||||
for (size_t i = 0; i < 5 && !loaded_remote_index; i++)
|
||||
{
|
||||
if (i)
|
||||
LOG(WARNING) << "Failed to download remote index, trying again... (" << i << ")";
|
||||
loaded_remote_index = download_index();
|
||||
}
|
||||
|
||||
if (load_local_index())
|
||||
{
|
||||
if (!loaded_remote_index)
|
||||
{
|
||||
LOG(WARNING) << "Failed to load remote index, attempting to use fallback.";
|
||||
use_fallback_remote();
|
||||
}
|
||||
else if (m_local_index.version < m_remote_index.version)
|
||||
{
|
||||
LOG(INFO) << "Languages outdated, downloading new translations.";
|
||||
|
||||
update_language_packs();
|
||||
m_local_index.version = m_remote_index.version;
|
||||
}
|
||||
load_translations();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (!loaded_remote_index)
|
||||
{
|
||||
LOG(WARNING) << "Failed to load remote index, unable to load translations.";
|
||||
return;
|
||||
}
|
||||
|
||||
LOG(INFO) << "Downloading translations...";
|
||||
|
||||
m_local_index.fallback_default_language = m_remote_index.default_lang;
|
||||
m_local_index.selected_language = m_remote_index.default_lang;
|
||||
m_local_index.version = m_remote_index.version;
|
||||
|
||||
load_translations();
|
||||
}
|
||||
|
||||
std::string_view translation_service::get_translation(const std::string_view translation_key) const
|
||||
{
|
||||
return get_translation(rage::joaat(translation_key));
|
||||
}
|
||||
|
||||
|
||||
std::string_view translation_service::get_translation(const rage::joaat_t translation_key) const
|
||||
{
|
||||
if (auto it = m_translations.find(translation_key); it != m_translations.end())
|
||||
return it->second.c_str();
|
||||
|
||||
return {0, 0};
|
||||
}
|
||||
|
||||
std::map<std::string, translation_entry>& translation_service::available_translations()
|
||||
{
|
||||
return m_remote_index.translations;
|
||||
}
|
||||
|
||||
const std::string& translation_service::current_language_pack()
|
||||
{
|
||||
return m_local_index.selected_language;
|
||||
}
|
||||
|
||||
void translation_service::select_language_pack(const std::string& pack_id)
|
||||
{
|
||||
g_thread_pool->push([this, &pack_id] {
|
||||
m_local_index.selected_language = pack_id;
|
||||
load_translations();
|
||||
});
|
||||
}
|
||||
|
||||
void translation_service::load_translations()
|
||||
{
|
||||
m_translations.clear();
|
||||
|
||||
// load default lang first to make sure there are fallback keys if another language pack doesn't have a certain key
|
||||
auto j = load_translation(m_remote_index.default_lang);
|
||||
for (auto& [key, value] : j.items())
|
||||
{
|
||||
m_translations.insert({rage::joaat(key), value.get<std::string>()});
|
||||
}
|
||||
|
||||
// Don't load selected language if it's the same as default
|
||||
if (m_local_index.selected_language != m_remote_index.default_lang)
|
||||
{
|
||||
auto j = load_translation(m_local_index.selected_language);
|
||||
for (auto& [key, value] : j.items())
|
||||
{
|
||||
m_translations[rage::joaat(key)] = value;
|
||||
}
|
||||
}
|
||||
|
||||
save_local_index();
|
||||
}
|
||||
|
||||
nlohmann::json translation_service::load_translation(const std::string_view pack_id)
|
||||
{
|
||||
auto file = m_translation_directory->get_file(std::format("./{}.json", pack_id));
|
||||
if (!file.exists())
|
||||
{
|
||||
LOG(INFO) << "Translations for '" << pack_id << "' does not exist, downloading from " << m_url;
|
||||
if (!download_language_pack(pack_id))
|
||||
{
|
||||
LOG(WARNING) << "Failed to download language pack, can't recover...";
|
||||
return {};
|
||||
}
|
||||
// make a copy available
|
||||
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));
|
||||
}
|
||||
|
||||
bool translation_service::download_language_pack(const std::string_view pack_id)
|
||||
{
|
||||
if (auto it = m_remote_index.translations.find(pack_id.data()); it != m_remote_index.translations.end())
|
||||
{
|
||||
cpr::Response response = cpr::Get(cpr::Url{m_url + "/" + it->second.file});
|
||||
|
||||
if (response.status_code == 200)
|
||||
{
|
||||
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);
|
||||
out_file << json.dump(4);
|
||||
out_file.close();
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void translation_service::update_language_packs()
|
||||
{
|
||||
for (auto item : std::filesystem::directory_iterator(m_translation_directory->get_path()))
|
||||
{
|
||||
const auto path = item.path();
|
||||
const auto stem = path.stem().string();
|
||||
if (stem == "index" || item.path().extension() != ".json")
|
||||
continue;
|
||||
|
||||
if (!download_language_pack(stem))
|
||||
{
|
||||
LOG(WARNING) << "Failed to update '" << stem << "' language pack";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool translation_service::download_index()
|
||||
{
|
||||
cpr::Response response = cpr::Get(cpr::Url{m_url + "/index.json"});
|
||||
|
||||
if (response.status_code == 200)
|
||||
{
|
||||
m_remote_index = nlohmann::json::parse(response.text);
|
||||
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool translation_service::load_local_index()
|
||||
{
|
||||
const auto local_index = m_translation_directory->get_file("./index.json");
|
||||
if (local_index.exists())
|
||||
{
|
||||
const auto path = local_index.get_path();
|
||||
m_local_index = nlohmann::json::parse(std::ifstream(path, std::ios::binary));
|
||||
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void translation_service::save_local_index()
|
||||
{
|
||||
nlohmann::json j = m_local_index;
|
||||
|
||||
const auto local_index = m_translation_directory->get_file("./index.json");
|
||||
|
||||
auto os = std::ofstream(local_index.get_path(), std::ios::binary | std::ios::trunc);
|
||||
os << j.dump(4);
|
||||
os.close();
|
||||
}
|
||||
|
||||
void translation_service::use_fallback_remote()
|
||||
{
|
||||
m_remote_index.default_lang = m_local_index.fallback_default_language;
|
||||
m_remote_index.translations = m_local_index.fallback_languages;
|
||||
}
|
||||
}
|
||||
#include "translation_service.hpp"
|
||||
|
||||
#include "file_manager.hpp"
|
||||
#include "thread_pool.hpp"
|
||||
|
||||
#include <cpr/cpr.h>
|
||||
|
||||
namespace big
|
||||
{
|
||||
translation_service::translation_service() :
|
||||
m_url("https://cdn.jsdelivr.net/gh/YimMenu/Translations@master")
|
||||
{
|
||||
}
|
||||
|
||||
void translation_service::init()
|
||||
{
|
||||
m_translation_directory = std::make_unique<folder>(g_file_manager->get_project_folder("./translations").get_path());
|
||||
|
||||
bool loaded_remote_index = false;
|
||||
for (size_t i = 0; i < 5 && !loaded_remote_index; i++)
|
||||
{
|
||||
if (i)
|
||||
LOG(WARNING) << "Failed to download remote index, trying again... (" << i << ")";
|
||||
loaded_remote_index = download_index();
|
||||
}
|
||||
|
||||
if (load_local_index())
|
||||
{
|
||||
if (!loaded_remote_index)
|
||||
{
|
||||
LOG(WARNING) << "Failed to load remote index, attempting to use fallback.";
|
||||
use_fallback_remote();
|
||||
}
|
||||
else if (m_local_index.version < m_remote_index.version)
|
||||
{
|
||||
LOG(INFO) << "Languages outdated, downloading new translations.";
|
||||
|
||||
update_language_packs();
|
||||
m_local_index.version = m_remote_index.version;
|
||||
}
|
||||
load_translations();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (!loaded_remote_index)
|
||||
{
|
||||
LOG(WARNING) << "Failed to load remote index, unable to load translations.";
|
||||
return;
|
||||
}
|
||||
|
||||
LOG(INFO) << "Downloading translations...";
|
||||
|
||||
m_local_index.fallback_default_language = m_remote_index.default_lang;
|
||||
m_local_index.selected_language = m_remote_index.default_lang;
|
||||
m_local_index.version = m_remote_index.version;
|
||||
|
||||
load_translations();
|
||||
}
|
||||
|
||||
std::string_view translation_service::get_translation(const std::string_view translation_key) const
|
||||
{
|
||||
return get_translation(rage::joaat(translation_key));
|
||||
}
|
||||
|
||||
|
||||
std::string_view translation_service::get_translation(const rage::joaat_t translation_key) const
|
||||
{
|
||||
if (auto it = m_translations.find(translation_key); it != m_translations.end())
|
||||
return it->second.c_str();
|
||||
|
||||
return {0, 0};
|
||||
}
|
||||
|
||||
std::map<std::string, translation_entry>& translation_service::available_translations()
|
||||
{
|
||||
return m_remote_index.translations;
|
||||
}
|
||||
|
||||
const std::string& translation_service::current_language_pack()
|
||||
{
|
||||
return m_local_index.selected_language;
|
||||
}
|
||||
|
||||
void translation_service::select_language_pack(const std::string& pack_id)
|
||||
{
|
||||
g_thread_pool->push([this, &pack_id] {
|
||||
m_local_index.selected_language = pack_id;
|
||||
load_translations();
|
||||
});
|
||||
}
|
||||
|
||||
void translation_service::update_language_packs()
|
||||
{
|
||||
for (auto item : std::filesystem::directory_iterator(m_translation_directory->get_path()))
|
||||
{
|
||||
const auto path = item.path();
|
||||
const auto stem = path.stem().string();
|
||||
if (stem == "index" || item.path().extension() != ".json")
|
||||
continue;
|
||||
|
||||
if (!download_language_pack(stem))
|
||||
{
|
||||
LOG(WARNING) << "Failed to update '" << stem << "' language pack";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void translation_service::load_translations()
|
||||
{
|
||||
m_translations.clear();
|
||||
|
||||
// load default lang first to make sure there are fallback keys if another language pack doesn't have a certain key
|
||||
auto j = load_translation(m_remote_index.default_lang);
|
||||
for (auto& [key, value] : j.items())
|
||||
{
|
||||
m_translations.insert({rage::joaat(key), value.get<std::string>()});
|
||||
}
|
||||
|
||||
// Don't load selected language if it's the same as default
|
||||
if (m_local_index.selected_language != m_remote_index.default_lang)
|
||||
{
|
||||
auto j = load_translation(m_local_index.selected_language);
|
||||
for (auto& [key, value] : j.items())
|
||||
{
|
||||
m_translations[rage::joaat(key)] = value;
|
||||
}
|
||||
}
|
||||
|
||||
save_local_index();
|
||||
}
|
||||
|
||||
nlohmann::json translation_service::load_translation(const std::string_view pack_id)
|
||||
{
|
||||
auto file = m_translation_directory->get_file(std::format("./{}.json", pack_id));
|
||||
if (!file.exists())
|
||||
{
|
||||
LOG(INFO) << "Translations for '" << pack_id << "' does not exist, downloading from " << m_url;
|
||||
if (!download_language_pack(pack_id))
|
||||
{
|
||||
LOG(WARNING) << "Failed to download language pack, can't recover...";
|
||||
return {};
|
||||
}
|
||||
// make a copy available
|
||||
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));
|
||||
}
|
||||
|
||||
bool translation_service::download_language_pack(const std::string_view pack_id)
|
||||
{
|
||||
if (auto it = m_remote_index.translations.find(pack_id.data()); it != m_remote_index.translations.end())
|
||||
{
|
||||
cpr::Response response = cpr::Get(cpr::Url{m_url + "/" + it->second.file});
|
||||
|
||||
if (response.status_code == 200)
|
||||
{
|
||||
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);
|
||||
out_file << json.dump(4);
|
||||
out_file.close();
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool translation_service::download_index()
|
||||
{
|
||||
cpr::Response response = cpr::Get(cpr::Url{m_url + "/index.json"});
|
||||
|
||||
if (response.status_code == 200)
|
||||
{
|
||||
m_remote_index = nlohmann::json::parse(response.text);
|
||||
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool translation_service::load_local_index()
|
||||
{
|
||||
const auto local_index = m_translation_directory->get_file("./index.json");
|
||||
if (local_index.exists())
|
||||
{
|
||||
const auto path = local_index.get_path();
|
||||
m_local_index = nlohmann::json::parse(std::ifstream(path, std::ios::binary));
|
||||
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void translation_service::save_local_index()
|
||||
{
|
||||
nlohmann::json j = m_local_index;
|
||||
|
||||
const auto local_index = m_translation_directory->get_file("./index.json");
|
||||
|
||||
auto os = std::ofstream(local_index.get_path(), std::ios::binary | std::ios::trunc);
|
||||
os << j.dump(4);
|
||||
os.close();
|
||||
}
|
||||
|
||||
void translation_service::use_fallback_remote()
|
||||
{
|
||||
m_remote_index.default_lang = m_local_index.fallback_default_language;
|
||||
m_remote_index.translations = m_local_index.fallback_languages;
|
||||
}
|
||||
}
|
||||
|
@ -1,87 +1,87 @@
|
||||
#pragma once
|
||||
#include "file_manager/folder.hpp"
|
||||
#include "gta/joaat.hpp"
|
||||
#include "local_index.hpp"
|
||||
#include "remote_index.hpp"
|
||||
|
||||
namespace big
|
||||
{
|
||||
using translation_map = std::unordered_map<rage::joaat_t, std::string>;
|
||||
|
||||
class translation_service
|
||||
{
|
||||
public:
|
||||
translation_service();
|
||||
virtual ~translation_service() = default;
|
||||
translation_service(const translation_service&) = delete;
|
||||
translation_service(translation_service&&) noexcept = delete;
|
||||
translation_service& operator=(const translation_service&) = delete;
|
||||
translation_service& operator=(translation_service&&) noexcept = delete;
|
||||
|
||||
void init();
|
||||
|
||||
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::map<std::string, translation_entry>& available_translations();
|
||||
const std::string& current_language_pack();
|
||||
void select_language_pack(const std::string& pack_id);
|
||||
|
||||
private:
|
||||
void load_translations();
|
||||
nlohmann::json load_translation(const std::string_view pack_id);
|
||||
|
||||
bool download_language_pack(const std::string_view pack_id);
|
||||
void update_language_packs();
|
||||
|
||||
/**
|
||||
* @brief Downloads the remote index to compare with our local index
|
||||
*
|
||||
* @return true
|
||||
* @return false
|
||||
*/
|
||||
bool download_index();
|
||||
bool load_local_index();
|
||||
void save_local_index();
|
||||
/**
|
||||
* @brief Attempts to load the remote from the local index fallback
|
||||
*/
|
||||
void use_fallback_remote();
|
||||
|
||||
private:
|
||||
const std::string m_url;
|
||||
std::unique_ptr<folder> m_translation_directory;
|
||||
local_index m_local_index;
|
||||
remote_index m_remote_index;
|
||||
|
||||
translation_map m_translations;
|
||||
};
|
||||
|
||||
inline auto g_translation_service = translation_service();
|
||||
|
||||
template<std::size_t N>
|
||||
struct TranslationLiteral
|
||||
{
|
||||
rage::joaat_t m_hash;
|
||||
char m_key[N]{};
|
||||
|
||||
consteval TranslationLiteral(char const (&pp)[N])
|
||||
{
|
||||
std::ranges::copy(pp, m_key);
|
||||
m_hash = rage::joaat(pp);
|
||||
};
|
||||
|
||||
const std::string_view translation() const
|
||||
{
|
||||
if (const auto translation = g_translation_service.get_translation(m_hash); translation.length())
|
||||
return translation;
|
||||
return m_key;
|
||||
}
|
||||
};
|
||||
|
||||
template<TranslationLiteral T>
|
||||
constexpr auto operator"" _T()
|
||||
{
|
||||
return T.translation();
|
||||
}
|
||||
#pragma once
|
||||
#include "file_manager/folder.hpp"
|
||||
#include "gta/joaat.hpp"
|
||||
#include "local_index.hpp"
|
||||
#include "remote_index.hpp"
|
||||
|
||||
namespace big
|
||||
{
|
||||
using translation_map = std::unordered_map<rage::joaat_t, std::string>;
|
||||
|
||||
class translation_service
|
||||
{
|
||||
public:
|
||||
translation_service();
|
||||
virtual ~translation_service() = default;
|
||||
translation_service(const translation_service&) = delete;
|
||||
translation_service(translation_service&&) noexcept = delete;
|
||||
translation_service& operator=(const translation_service&) = delete;
|
||||
translation_service& operator=(translation_service&&) noexcept = delete;
|
||||
|
||||
void init();
|
||||
|
||||
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::map<std::string, translation_entry>& available_translations();
|
||||
const std::string& current_language_pack();
|
||||
void select_language_pack(const std::string& pack_id);
|
||||
void update_language_packs();
|
||||
|
||||
private:
|
||||
void load_translations();
|
||||
nlohmann::json load_translation(const std::string_view pack_id);
|
||||
|
||||
bool download_language_pack(const std::string_view pack_id);
|
||||
|
||||
/**
|
||||
* @brief Downloads the remote index to compare with our local index
|
||||
*
|
||||
* @return true
|
||||
* @return false
|
||||
*/
|
||||
bool download_index();
|
||||
bool load_local_index();
|
||||
void save_local_index();
|
||||
/**
|
||||
* @brief Attempts to load the remote from the local index fallback
|
||||
*/
|
||||
void use_fallback_remote();
|
||||
|
||||
private:
|
||||
const std::string m_url;
|
||||
std::unique_ptr<folder> m_translation_directory;
|
||||
local_index m_local_index;
|
||||
remote_index m_remote_index;
|
||||
|
||||
translation_map m_translations;
|
||||
};
|
||||
|
||||
inline auto g_translation_service = translation_service();
|
||||
|
||||
template<std::size_t N>
|
||||
struct TranslationLiteral
|
||||
{
|
||||
rage::joaat_t m_hash;
|
||||
char m_key[N]{};
|
||||
|
||||
consteval TranslationLiteral(char const (&pp)[N])
|
||||
{
|
||||
std::ranges::copy(pp, m_key);
|
||||
m_hash = rage::joaat(pp);
|
||||
};
|
||||
|
||||
const std::string_view translation() const
|
||||
{
|
||||
if (const auto translation = g_translation_service.get_translation(m_hash); translation.length())
|
||||
return translation;
|
||||
return m_key;
|
||||
}
|
||||
};
|
||||
|
||||
template<TranslationLiteral T>
|
||||
constexpr auto operator"" _T()
|
||||
{
|
||||
return T.translation();
|
||||
}
|
||||
}
|
@ -187,7 +187,7 @@ namespace big
|
||||
4.f,
|
||||
5.f);
|
||||
//LOG(INFO) << "Navmesh probably failed, issiuing regular task ";
|
||||
g_notification_service->push_warning("Vehicle controller", "Your vehicle could not assess an accurate path, it will try something else");
|
||||
g_notification_service->push_warning("VEHICLE_CONTROLLER"_T.data(), "VEHICLE_CONTROLLER_TRY_ALT_PATHFINDING"_T.data());
|
||||
script::get_current()->yield(500ms);
|
||||
}
|
||||
|
||||
@ -331,12 +331,12 @@ namespace big
|
||||
if (vehicle_control::find_suitable_destination_near_player(destination, heading))
|
||||
{
|
||||
//LOG(INFO) << "Suitable destination found";
|
||||
g_notification_service->push_warning("Vehicle controller", "Found a nice spot, your vehicle is on its way");
|
||||
g_notification_service->push_warning("VEHICLE_CONTROLLER"_T.data(), "VEHICLE_CONTROLLER_FOUND_LOCATION"_T.data());
|
||||
}
|
||||
else
|
||||
{
|
||||
//LOG(INFO) << "Couldn't find suitable destionation, defaulting to offset of player\nThis might go wrong";
|
||||
g_notification_service->push_warning("Vehicle controller", "Couldn't locate an accurate spot, your vehicle is on its way regardless");
|
||||
g_notification_service->push_warning("VEHICLE_CONTROLLER"_T.data(), "VEHICLE_CONTROLLER_FORCE_PATHFINDING"_T.data());
|
||||
destination = behind_pos;
|
||||
}
|
||||
|
||||
@ -359,7 +359,7 @@ namespace big
|
||||
else
|
||||
{
|
||||
//LOG(INFO) << "Navmesh load failed";
|
||||
g_notification_service->push_error("Nav mesh", "Failed loading the navmesh");
|
||||
g_notification_service->push_error("VEHICLE_CONTROLLER"_T.data(), "VEHICLE_CONTROLLER_NAVMESH_FAILURE"_T.data());
|
||||
m_driver_performing_task = false;
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user