2022-07-19 18:19:19 +08:00
|
|
|
#include "api/remote.hpp"
|
|
|
|
#include "file_manager.hpp"
|
|
|
|
#include "thread_pool.hpp"
|
|
|
|
#include "gta_data_service.hpp"
|
|
|
|
|
2022-07-29 19:51:19 +08:00
|
|
|
#define EXIST_IN_ARRAY(arr, val) (std::find(std::begin(arr), std::end(arr), val) != std::end(arr))
|
|
|
|
|
2022-07-19 18:19:19 +08:00
|
|
|
namespace big
|
|
|
|
{
|
2022-07-29 19:51:19 +08:00
|
|
|
gta_data_service::gta_data_service()
|
2022-07-19 18:19:19 +08:00
|
|
|
{
|
2022-08-13 23:17:59 +08:00
|
|
|
g_thread_pool->push([this] {
|
|
|
|
while (!g_running)
|
|
|
|
std::this_thread::sleep_for(1s);
|
|
|
|
|
|
|
|
const std::string url_prefix = "http://github-proxy.damon.sh/DurtyFree/gta-v-data-dumps/master/";
|
|
|
|
|
|
|
|
this->load_from_file(
|
|
|
|
"./lib/vehicles.json",
|
|
|
|
"./lib/vehicles_etag.txt",
|
|
|
|
url_prefix + "vehicles.json",
|
|
|
|
>a_data_service::load_vehicles,
|
|
|
|
"Vehicle"
|
|
|
|
);
|
|
|
|
|
|
|
|
std::this_thread::sleep_for(1s);
|
|
|
|
|
|
|
|
this->load_from_file(
|
|
|
|
"./lib/peds.json",
|
|
|
|
"./lib/peds_etag.txt",
|
|
|
|
url_prefix + "peds.json",
|
|
|
|
>a_data_service::load_peds,
|
|
|
|
"Ped"
|
|
|
|
);
|
|
|
|
|
|
|
|
std::this_thread::sleep_for(1s);
|
|
|
|
|
|
|
|
this->load_from_file(
|
|
|
|
"./lib/weapons.json",
|
|
|
|
"./lib/weapons_etag.txt",
|
|
|
|
url_prefix + "weapons.json",
|
|
|
|
>a_data_service::load_weapons,
|
|
|
|
"Weapon"
|
|
|
|
);
|
|
|
|
});
|
2022-07-29 19:51:19 +08:00
|
|
|
|
2022-07-19 18:19:19 +08:00
|
|
|
g_gta_data_service = this;
|
|
|
|
}
|
|
|
|
|
|
|
|
gta_data_service::~gta_data_service()
|
|
|
|
{
|
|
|
|
g_gta_data_service = nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
const vehicle_item& gta_data_service::find_vehicle_by_hash(Hash hash)
|
|
|
|
{
|
|
|
|
int idx = -1;
|
|
|
|
|
|
|
|
if (m_vehicle_hash_idx_map.count(hash))
|
|
|
|
{
|
|
|
|
idx = m_vehicle_hash_idx_map[hash];
|
|
|
|
}
|
|
|
|
|
|
|
|
if (idx == -1)
|
|
|
|
{
|
|
|
|
return empty_vehicle_item;
|
|
|
|
}
|
2022-07-29 19:51:19 +08:00
|
|
|
|
|
|
|
return m_vehicle_item_arr[idx];
|
2022-07-19 18:19:19 +08:00
|
|
|
}
|
|
|
|
|
2022-07-29 19:51:19 +08:00
|
|
|
const std::vector<std::string>& gta_data_service::get_vehicle_class_arr()
|
2022-07-19 18:19:19 +08:00
|
|
|
{
|
|
|
|
return m_vehicle_class_arr;
|
|
|
|
}
|
|
|
|
|
2022-07-29 19:51:19 +08:00
|
|
|
const std::vector<vehicle_item>& gta_data_service::get_vehicle_arr()
|
2022-07-19 18:19:19 +08:00
|
|
|
{
|
|
|
|
return m_vehicle_item_arr;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const ped_item& gta_data_service::find_ped_by_hash(Hash hash)
|
|
|
|
{
|
|
|
|
int idx = -1;
|
|
|
|
|
|
|
|
if (m_ped_hash_idx_map.count(hash))
|
|
|
|
{
|
|
|
|
idx = m_ped_hash_idx_map[hash];
|
|
|
|
}
|
|
|
|
|
|
|
|
if (idx == -1)
|
|
|
|
{
|
|
|
|
return empty_ped_item;
|
|
|
|
}
|
2022-07-29 19:51:19 +08:00
|
|
|
|
|
|
|
return m_ped_item_arr[idx];
|
2022-07-19 18:19:19 +08:00
|
|
|
}
|
|
|
|
|
2022-07-29 19:51:19 +08:00
|
|
|
const std::vector<std::string>& gta_data_service::get_ped_type_arr()
|
2022-07-19 18:19:19 +08:00
|
|
|
{
|
|
|
|
return m_ped_type_arr;
|
|
|
|
}
|
|
|
|
|
2022-07-29 19:51:19 +08:00
|
|
|
const std::vector<ped_item>& gta_data_service::get_ped_arr()
|
2022-07-19 18:19:19 +08:00
|
|
|
{
|
|
|
|
return m_ped_item_arr;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2022-07-29 19:51:19 +08:00
|
|
|
const weapon_item& gta_data_service::find_weapon_by_hash(Hash hash)
|
|
|
|
{
|
|
|
|
int idx = -1;
|
|
|
|
|
|
|
|
if (m_weapon_hash_idx_map.count(hash))
|
|
|
|
{
|
|
|
|
idx = m_weapon_hash_idx_map[hash];
|
|
|
|
}
|
2022-07-19 18:19:19 +08:00
|
|
|
|
2022-07-29 19:51:19 +08:00
|
|
|
if (idx == -1)
|
|
|
|
{
|
|
|
|
return empty_weapon_item;
|
|
|
|
}
|
|
|
|
|
|
|
|
return m_weapon_item_arr[idx];
|
|
|
|
}
|
|
|
|
|
|
|
|
const std::vector<std::string>& gta_data_service::get_weapon_type_arr()
|
|
|
|
{
|
|
|
|
return m_weapon_type_arr;
|
|
|
|
}
|
|
|
|
|
|
|
|
const std::vector<weapon_item>& gta_data_service::get_weapon_arr()
|
|
|
|
{
|
|
|
|
return m_weapon_item_arr;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2022-08-13 23:17:59 +08:00
|
|
|
void gta_data_service::load_from_file(
|
|
|
|
std::string file_path, std::string etag_path, std::string url,
|
|
|
|
bool(gta_data_service::* load_func)(std::filesystem::path), std::string data_name
|
|
|
|
) {
|
2022-07-29 19:51:19 +08:00
|
|
|
file file_to_load(g_file_manager->get_project_file(file_path));
|
2022-08-13 23:17:59 +08:00
|
|
|
file file_etag(g_file_manager->get_project_file(etag_path));
|
|
|
|
auto file_to_load_path = file_to_load.get_path();
|
|
|
|
auto file_etag_path = file_etag.get_path();
|
2022-07-29 19:51:19 +08:00
|
|
|
|
2022-08-13 23:17:59 +08:00
|
|
|
bool up_to_date = false;
|
2022-07-19 18:19:19 +08:00
|
|
|
|
2022-08-13 23:17:59 +08:00
|
|
|
for (int retry = 0; retry < 3 && g_running; retry++)
|
|
|
|
{
|
|
|
|
LOG(INFO) << "Checking update (attempt: " << (retry + 1) << "/3): " << data_name;
|
2022-07-29 19:51:19 +08:00
|
|
|
|
2022-08-13 23:17:59 +08:00
|
|
|
try
|
2022-07-19 18:19:19 +08:00
|
|
|
{
|
|
|
|
bool ret = remote::update_binary(
|
|
|
|
url,
|
2022-08-13 23:17:59 +08:00
|
|
|
file_to_load_path,
|
|
|
|
file_etag_path
|
2022-07-19 18:19:19 +08:00
|
|
|
);
|
|
|
|
|
|
|
|
if (ret)
|
|
|
|
{
|
2022-08-13 23:17:59 +08:00
|
|
|
up_to_date = true;
|
|
|
|
|
|
|
|
LOG(INFO) << "Data updated: " << data_name;
|
|
|
|
|
|
|
|
if ((this->*load_func)(file_to_load_path))
|
2022-08-13 17:19:18 +08:00
|
|
|
{
|
|
|
|
LOG(INFO) << "Data loaded: " + data_name;
|
2022-08-13 23:17:59 +08:00
|
|
|
break;
|
2022-08-13 17:19:18 +08:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2022-08-13 23:17:59 +08:00
|
|
|
std::filesystem::remove(file_to_load_path);
|
|
|
|
std::filesystem::remove(file_etag_path);
|
2022-08-13 17:19:18 +08:00
|
|
|
}
|
2022-07-19 18:19:19 +08:00
|
|
|
}
|
2022-08-13 23:17:59 +08:00
|
|
|
}
|
|
|
|
catch (...)
|
|
|
|
{
|
|
|
|
LOG(WARNING) << "Data invalid: " + data_name;
|
|
|
|
}
|
|
|
|
|
|
|
|
std::this_thread::sleep_for(2s);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!up_to_date)
|
|
|
|
{
|
|
|
|
LOG(WARNING) << "Data not updated: " + data_name;
|
|
|
|
|
|
|
|
try
|
|
|
|
{
|
|
|
|
if (file_to_load.exists())
|
2022-07-19 18:19:19 +08:00
|
|
|
{
|
2022-08-13 23:17:59 +08:00
|
|
|
if ((this->*load_func)(file_to_load_path))
|
|
|
|
{
|
|
|
|
LOG(INFO) << "Cache loaded: " + data_name;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
std::filesystem::remove(file_to_load_path);
|
|
|
|
std::filesystem::remove(file_etag_path);
|
|
|
|
throw std::exception("");
|
|
|
|
}
|
2022-07-19 18:19:19 +08:00
|
|
|
}
|
|
|
|
}
|
2022-08-13 23:17:59 +08:00
|
|
|
catch (...)
|
|
|
|
{
|
|
|
|
LOG(WARNING) << "Cache invalid: " + data_name;
|
|
|
|
}
|
|
|
|
}
|
2022-07-19 18:19:19 +08:00
|
|
|
}
|
|
|
|
|
2022-08-13 23:17:59 +08:00
|
|
|
bool gta_data_service::load_vehicles(std::filesystem::path path)
|
2022-07-19 18:19:19 +08:00
|
|
|
{
|
2022-08-13 23:17:59 +08:00
|
|
|
std::ifstream file(path);
|
2022-07-19 18:19:19 +08:00
|
|
|
nlohmann::json all_vehicles;
|
|
|
|
|
|
|
|
try
|
|
|
|
{
|
|
|
|
file >> all_vehicles;
|
|
|
|
|
2022-08-13 17:19:18 +08:00
|
|
|
if (!all_vehicles.is_array())
|
|
|
|
{
|
2022-08-13 19:29:33 +08:00
|
|
|
throw std::exception("Invalid json format.");
|
2022-07-19 18:19:19 +08:00
|
|
|
}
|
|
|
|
|
2022-08-13 17:19:18 +08:00
|
|
|
m_vehicle_class_arr.clear();
|
|
|
|
m_vehicle_hash_idx_map.clear();
|
|
|
|
m_vehicle_item_arr.clear();
|
2022-07-19 18:19:19 +08:00
|
|
|
|
2022-08-13 17:19:18 +08:00
|
|
|
for (auto& item_json : all_vehicles)
|
|
|
|
{
|
|
|
|
if (
|
|
|
|
item_json["Hash"].is_null() ||
|
|
|
|
item_json["Name"].is_null() ||
|
2022-09-08 16:30:17 +03:00
|
|
|
item_json["MonetaryValue"] == 0 ||
|
2022-08-13 17:19:18 +08:00
|
|
|
!item_json["Bones"].is_array() ||
|
|
|
|
item_json["Bones"][0] == "stub"
|
|
|
|
) {
|
|
|
|
continue;
|
|
|
|
}
|
2022-07-19 18:19:19 +08:00
|
|
|
|
2022-08-13 17:19:18 +08:00
|
|
|
auto item = vehicle_item(item_json);
|
2022-07-19 18:19:19 +08:00
|
|
|
|
2022-08-13 17:19:18 +08:00
|
|
|
m_vehicle_hash_idx_map[item_json["Hash"]] = (int)m_vehicle_item_arr.size();
|
|
|
|
|
|
|
|
m_vehicle_item_arr.push_back(item);
|
|
|
|
|
|
|
|
if (std::find(m_vehicle_class_arr.begin(), m_vehicle_class_arr.end(), item.clazz) == m_vehicle_class_arr.end())
|
|
|
|
{
|
|
|
|
m_vehicle_class_arr.push_back(item.clazz);
|
|
|
|
}
|
2022-07-19 18:19:19 +08:00
|
|
|
|
2022-08-13 17:19:18 +08:00
|
|
|
std::sort(m_vehicle_class_arr.begin(), m_vehicle_class_arr.end());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
catch (const std::exception& ex)
|
|
|
|
{
|
|
|
|
LOG(WARNING) << "Failed to load vehicles.json:\n" << ex.what();
|
|
|
|
return false;
|
2022-07-19 18:19:19 +08:00
|
|
|
}
|
2022-08-13 17:19:18 +08:00
|
|
|
|
|
|
|
return true;
|
2022-07-19 18:19:19 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2022-08-13 23:17:59 +08:00
|
|
|
bool gta_data_service::load_peds(std::filesystem::path path)
|
2022-07-19 18:19:19 +08:00
|
|
|
{
|
2022-08-13 23:17:59 +08:00
|
|
|
std::ifstream file(path);
|
2022-07-19 18:19:19 +08:00
|
|
|
nlohmann::json all_peds;
|
|
|
|
|
|
|
|
try
|
|
|
|
{
|
|
|
|
file >> all_peds;
|
|
|
|
|
2022-08-13 17:19:18 +08:00
|
|
|
if (!all_peds.is_array())
|
|
|
|
{
|
2022-08-13 19:29:33 +08:00
|
|
|
throw std::exception("Invalid json format.");
|
2022-07-19 18:19:19 +08:00
|
|
|
}
|
|
|
|
|
2022-08-13 17:19:18 +08:00
|
|
|
m_ped_type_arr.clear();
|
|
|
|
m_ped_hash_idx_map.clear();
|
|
|
|
m_ped_item_arr.clear();
|
2022-07-19 18:19:19 +08:00
|
|
|
|
2022-08-13 17:19:18 +08:00
|
|
|
for (auto& item_json : all_peds)
|
|
|
|
{
|
|
|
|
if (
|
|
|
|
item_json["Hash"].is_null() ||
|
|
|
|
item_json["Name"].is_null()
|
|
|
|
) {
|
|
|
|
continue;
|
|
|
|
}
|
2022-07-19 18:19:19 +08:00
|
|
|
|
2022-08-13 17:19:18 +08:00
|
|
|
auto item = ped_item(item_json);
|
2022-07-19 18:19:19 +08:00
|
|
|
|
2022-08-13 17:19:18 +08:00
|
|
|
m_ped_hash_idx_map[item_json["Hash"]] = (int)m_ped_item_arr.size();
|
|
|
|
|
|
|
|
m_ped_item_arr.push_back(item);
|
|
|
|
|
|
|
|
if (std::find(m_ped_type_arr.begin(), m_ped_type_arr.end(), item.ped_type) == m_ped_type_arr.end())
|
|
|
|
{
|
|
|
|
m_ped_type_arr.push_back(item.ped_type);
|
|
|
|
}
|
2022-07-19 18:19:19 +08:00
|
|
|
|
2022-08-13 17:19:18 +08:00
|
|
|
std::sort(m_ped_type_arr.begin(), m_ped_type_arr.end());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
catch (const std::exception& ex)
|
|
|
|
{
|
|
|
|
LOG(WARNING) << "Failed to load peds.json:\n" << ex.what();
|
|
|
|
return false;
|
2022-07-19 18:19:19 +08:00
|
|
|
}
|
2022-08-13 17:19:18 +08:00
|
|
|
|
|
|
|
return true;
|
2022-07-19 18:19:19 +08:00
|
|
|
}
|
2022-07-29 19:51:19 +08:00
|
|
|
|
|
|
|
|
2022-08-13 23:17:59 +08:00
|
|
|
bool gta_data_service::load_weapons(std::filesystem::path path)
|
2022-07-29 19:51:19 +08:00
|
|
|
{
|
2022-08-13 23:17:59 +08:00
|
|
|
std::ifstream file(path);
|
2022-07-29 19:51:19 +08:00
|
|
|
nlohmann::json all_weapons;
|
|
|
|
|
|
|
|
try
|
|
|
|
{
|
|
|
|
file >> all_weapons;
|
|
|
|
|
2022-08-13 17:19:18 +08:00
|
|
|
if (!all_weapons.is_array())
|
|
|
|
{
|
2022-08-13 19:29:33 +08:00
|
|
|
throw std::exception("Invalid json format.");
|
2022-07-29 19:51:19 +08:00
|
|
|
}
|
|
|
|
|
2022-08-13 17:19:18 +08:00
|
|
|
m_weapon_type_arr.clear();
|
|
|
|
m_weapon_hash_idx_map.clear();
|
|
|
|
m_weapon_item_arr.clear();
|
|
|
|
|
|
|
|
constexpr Hash hash_blacklist_arr[] = {
|
|
|
|
RAGE_JOAAT("WEAPON_BIRD_CRAP"),
|
|
|
|
RAGE_JOAAT("WEAPON_DIGISCANNER"),
|
|
|
|
RAGE_JOAAT("WEAPON_GARBAGEBAG"),
|
|
|
|
RAGE_JOAAT("WEAPON_GRENADELAUNCHER_SMOKE"),
|
|
|
|
RAGE_JOAAT("WEAPON_HANDCUFFS"),
|
|
|
|
RAGE_JOAAT("WEAPON_METALDETECTOR"),
|
|
|
|
RAGE_JOAAT("GADGET_NIGHTVISION"),
|
|
|
|
RAGE_JOAAT("GADGET_PARACHUTE"),
|
|
|
|
RAGE_JOAAT("WEAPON_TRANQUILIZER"),
|
|
|
|
RAGE_JOAAT("WEAPON_STINGER")
|
|
|
|
};
|
|
|
|
|
|
|
|
for (auto& item_json : all_weapons)
|
2022-07-29 19:51:19 +08:00
|
|
|
{
|
2022-08-13 17:19:18 +08:00
|
|
|
if (
|
|
|
|
item_json["Hash"].is_null() ||
|
|
|
|
item_json["Name"].is_null() ||
|
|
|
|
item_json["IsVehicleWeapon"]
|
|
|
|
) {
|
|
|
|
continue;
|
|
|
|
}
|
2022-07-29 19:51:19 +08:00
|
|
|
|
2022-08-13 17:19:18 +08:00
|
|
|
if (EXIST_IN_ARRAY(hash_blacklist_arr, item_json["Hash"]))
|
|
|
|
{
|
|
|
|
continue;
|
|
|
|
}
|
2022-07-29 19:51:19 +08:00
|
|
|
|
2022-08-13 17:19:18 +08:00
|
|
|
auto item = weapon_item(item_json);
|
2022-07-29 19:51:19 +08:00
|
|
|
|
2022-08-13 17:19:18 +08:00
|
|
|
if (item.name == "Invalid" || item.name == "Unarmed" || item.weapon_type == "NULL")
|
|
|
|
{
|
|
|
|
continue;
|
|
|
|
}
|
2022-07-29 19:51:19 +08:00
|
|
|
|
2022-08-13 17:19:18 +08:00
|
|
|
m_weapon_hash_idx_map[item_json["Hash"]] = (int)m_weapon_item_arr.size();
|
2022-07-29 19:51:19 +08:00
|
|
|
|
2022-08-13 17:19:18 +08:00
|
|
|
m_weapon_item_arr.push_back(item);
|
|
|
|
|
|
|
|
if (std::find(m_weapon_type_arr.begin(), m_weapon_type_arr.end(), item.weapon_type) == m_weapon_type_arr.end())
|
|
|
|
{
|
|
|
|
m_weapon_type_arr.push_back(item.weapon_type);
|
|
|
|
}
|
|
|
|
|
|
|
|
std::sort(m_weapon_type_arr.begin(), m_weapon_type_arr.end());
|
2022-07-29 19:51:19 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
}
|
2022-08-13 17:19:18 +08:00
|
|
|
catch (const std::exception& ex)
|
|
|
|
{
|
|
|
|
LOG(WARNING) << "Failed to load weapons.json:\n" << ex.what();
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
2022-07-29 19:51:19 +08:00
|
|
|
}
|
2022-07-19 18:19:19 +08:00
|
|
|
}
|