feat(cache): expand ped (#1156)

This commit is contained in:
Aure7138 2023-04-02 00:37:26 +08:00 committed by GitHub
parent 4922e60d89
commit 205836dd74
14 changed files with 215 additions and 62 deletions

View File

@ -3,7 +3,7 @@ include(FetchContent)
FetchContent_Declare( FetchContent_Declare(
gtav_classes gtav_classes
GIT_REPOSITORY https://github.com/Yimura/GTAV-Classes.git GIT_REPOSITORY https://github.com/Yimura/GTAV-Classes.git
GIT_TAG 56aeddea31d677efa0e5c4f84b4f353d420a8502 GIT_TAG cf7c1a71b413788371000b56d40c4e8b81c47a2c
GIT_PROGRESS TRUE GIT_PROGRESS TRUE
CONFIGURE_COMMAND "" CONFIGURE_COMMAND ""
BUILD_COMMAND "" BUILD_COMMAND ""

View File

@ -1,6 +1,6 @@
#include "fidevice.hpp" #include "fidevice.hpp"
#include "pointers.hpp" #include "pointers.hpp"
#include "hooking.hpp"
namespace rage namespace rage
{ {
@ -262,6 +262,6 @@ namespace rage
bool fiPackfile::Mount(const char* mount_point) bool fiPackfile::Mount(const char* mount_point)
{ {
return big::g_pointers->m_fipackfile_mount(this, mount_point); return big::g_hooking->get_original<big::hooks::fipackfile_mount>()(this, mount_point);
} }
} }

View File

@ -121,6 +121,8 @@ namespace big
detour_hook_helper::add<hooks::write_vehicle_proximity_migration_data_node>("WVPMDN", g_pointers->m_write_vehicle_proximity_migration_data_node); detour_hook_helper::add<hooks::write_vehicle_proximity_migration_data_node>("WVPMDN", g_pointers->m_write_vehicle_proximity_migration_data_node);
detour_hook_helper::add<hooks::fipackfile_mount>("FPFM", g_pointers->m_fipackfile_mount);
g_hooking = this; g_hooking = this;
} }

View File

@ -163,6 +163,8 @@ namespace big
static HRESULT direct_sound_capture_create(GUID* guid, IDirectSoundCapture** sound, void* unknown); static HRESULT direct_sound_capture_create(GUID* guid, IDirectSoundCapture** sound, void* unknown);
static void write_vehicle_proximity_migration_data_node(rage::netObject* veh, CVehicleProximityMigrationDataNode* node); static void write_vehicle_proximity_migration_data_node(rage::netObject* veh, CVehicleProximityMigrationDataNode* node);
static bool fipackfile_mount(rage::fiPackfile* this_, const char* mount_point);
}; };
class minhook_keepalive class minhook_keepalive

View File

@ -0,0 +1,44 @@
#include "hooking.hpp"
#include "gta/fidevice.hpp"
#include "services/gta_data/yim_fipackfile.hpp"
#include "services/gta_data/gta_data_service.hpp"
namespace big
{
bool hooks::fipackfile_mount(rage::fiPackfile* this_, const char* mount_point)
{
static bool init = ([] {
if(g_gta_data_service->state() == eGtaDataUpdateState::ON_INIT_WAITING)
g_gta_data_service->set_state(eGtaDataUpdateState::ON_INIT_UPDATE_START);
}(),true);
auto result = g_hooking->get_original<fipackfile_mount>()(this_, mount_point);
if (g_gta_data_service->state() == eGtaDataUpdateState::ON_INIT_UPDATE_START)
{
yim_fipackfile rpf_wrapper = yim_fipackfile(this_, mount_point);
std::for_each(yim_fipackfile::m_wrapper_call_back.begin(), yim_fipackfile::m_wrapper_call_back.end(), [&rpf_wrapper](std::function<size_t(yim_fipackfile & rpf_wrapper)> cb) {
cb(rpf_wrapper);
});
if (!stricmp(this_->GetName(), "BgScript.rpf"))
{
auto names = yim_fipackfile::get_non_dlc_mounted_devices_names();
for (auto name : names)
{
auto device = rage::fiDevice::GetDevice(name.c_str(), true);
if (*(void**)this_ == *(void**)device) //make sure it's fipackfile
{
rpf_wrapper = yim_fipackfile((rage::fiPackfile*)device, name);
std::for_each(yim_fipackfile::m_wrapper_call_back.begin(), yim_fipackfile::m_wrapper_call_back.end(), [&rpf_wrapper](std::function<size_t(yim_fipackfile & rpf_wrapper)> cb) {
cb(rpf_wrapper);
});
}
}
g_gta_data_service->set_state(eGtaDataUpdateState::ON_INIT_UPDATE_END);
}
}
return result;
}
}

View File

@ -11,7 +11,6 @@
#include "script_mgr.hpp" #include "script_mgr.hpp"
#include "services/api/api_service.hpp" #include "services/api/api_service.hpp"
#include "services/context_menu/context_menu_service.hpp" #include "services/context_menu/context_menu_service.hpp"
#include "services/orbital_drone/orbital_drone.hpp"
#include "services/custom_text/custom_text_service.hpp" #include "services/custom_text/custom_text_service.hpp"
#include "services/globals/globals_service.hpp" #include "services/globals/globals_service.hpp"
#include "services/gta_data/gta_data_service.hpp" #include "services/gta_data/gta_data_service.hpp"
@ -21,6 +20,7 @@
#include "services/mobile/mobile_service.hpp" #include "services/mobile/mobile_service.hpp"
#include "services/model_preview/model_preview_service.hpp" #include "services/model_preview/model_preview_service.hpp"
#include "services/notifications/notification_service.hpp" #include "services/notifications/notification_service.hpp"
#include "services/orbital_drone/orbital_drone.hpp"
#include "services/pickups/pickup_service.hpp" #include "services/pickups/pickup_service.hpp"
#include "services/player_database/player_database_service.hpp" #include "services/player_database/player_database_service.hpp"
#include "services/players/player_service.hpp" #include "services/players/player_service.hpp"
@ -116,7 +116,7 @@ BOOL APIENTRY DllMain(HMODULE hmod, DWORD reason, PVOID)
g_script_mgr.add_script(std::make_unique<script>(&backend::world_loop, "World")); g_script_mgr.add_script(std::make_unique<script>(&backend::world_loop, "World"));
g_script_mgr.add_script(std::make_unique<script>(&backend::orbital_drone, "Orbital Drone")); g_script_mgr.add_script(std::make_unique<script>(&backend::orbital_drone, "Orbital Drone"));
g_script_mgr.add_script(std::make_unique<script>(&context_menu_service::context_menu, "Context Menu")); g_script_mgr.add_script(std::make_unique<script>(&context_menu_service::context_menu, "Context Menu"));
LOG(INFO) << "Scripts registered."; LOG(INFO) << "Scripts registered.";
g_hooking->enable(); g_hooking->enable();

View File

@ -33,7 +33,7 @@ namespace big
// Game State // Game State
main_batch.add("GS", "83 3D ? ? ? ? ? 75 17 8B 43 20 25", [this](memory::handle ptr) { main_batch.add("GS", "83 3D ? ? ? ? ? 75 17 8B 43 20 25", [this](memory::handle ptr) {
m_game_state = ptr.add(2).rip().as<eGameState*>(); m_game_state = ptr.add(2).rip().add(1).as<eGameState*>();
}); });
// Is Session Started // Is Session Started

View File

@ -9,6 +9,9 @@
#include "thread_pool.hpp" #include "thread_pool.hpp"
#include "util/session.hpp" #include "util/session.hpp"
#include "yim_fipackfile.hpp" #include "yim_fipackfile.hpp"
#include "util/vehicle.hpp"
#include "util/misc.hpp"
#include "util/model_info.hpp"
namespace big namespace big
{ {
@ -50,6 +53,11 @@ namespace big
return m_update_state; return m_update_state;
} }
void gta_data_service::set_state(eGtaDataUpdateState state)
{
m_update_state = state;
}
void gta_data_service::update_in_online() void gta_data_service::update_in_online()
{ {
m_update_state = eGtaDataUpdateState::WAITING_FOR_SINGLE_PLAYER; m_update_state = eGtaDataUpdateState::WAITING_FOR_SINGLE_PLAYER;
@ -66,7 +74,7 @@ namespace big
{ {
script::get_current()->yield(100ms); script::get_current()->yield(100ms);
} }
m_update_state = eGtaDataUpdateState::UPDATING;
rebuild_cache(); rebuild_cache();
}); });
} }
@ -75,6 +83,15 @@ namespace big
{ {
m_update_state = eGtaDataUpdateState::WAITING_FOR_SINGLE_PLAYER; m_update_state = eGtaDataUpdateState::WAITING_FOR_SINGLE_PLAYER;
g_fiber_pool->queue_job([this] { g_fiber_pool->queue_job([this] {
m_update_state = eGtaDataUpdateState::UPDATING;
rebuild_cache();
});
}
void gta_data_service::update_on_init()
{
m_update_state = eGtaDataUpdateState::ON_INIT_WAITING;
g_thread_pool->push([this] {
rebuild_cache(); rebuild_cache();
}); });
} }
@ -226,8 +243,6 @@ namespace big
void gta_data_service::rebuild_cache() void gta_data_service::rebuild_cache()
{ {
m_update_state = eGtaDataUpdateState::UPDATING;
using hash_array = std::vector<std::uint32_t>; using hash_array = std::vector<std::uint32_t>;
hash_array mapped_peds; hash_array mapped_peds;
hash_array mapped_vehicles; hash_array mapped_vehicles;
@ -243,7 +258,7 @@ namespace big
LOG(INFO) << "Rebuilding cache started..."; LOG(INFO) << "Rebuilding cache started...";
yim_fipackfile::for_each_fipackfile([&](yim_fipackfile& rpf_wrapper) { yim_fipackfile::add_wrapper_call_back([&](yim_fipackfile& rpf_wrapper) {
const auto files = rpf_wrapper.get_file_paths(); const auto files = rpf_wrapper.get_file_paths();
for (const auto& file : files) for (const auto& file : files)
{ {
@ -281,14 +296,15 @@ namespace big
std::strncpy(veh.m_name, name, sizeof(veh.m_name)); std::strncpy(veh.m_name, name, sizeof(veh.m_name));
const auto manufacturer_display = item.child("vehicleMakeName").text().as_string(); const auto manufacturer_display = item.child("vehicleMakeName").text().as_string();
std::strncpy(veh.m_display_manufacturer, HUD::GET_FILENAME_FOR_AUDIO_CONVERSATION(manufacturer_display), sizeof(veh.m_display_manufacturer)); std::strncpy(veh.m_display_manufacturer, manufacturer_display, sizeof(veh.m_display_manufacturer));
const auto game_name = item.child("gameName").text().as_string(); const auto game_name = item.child("gameName").text().as_string();
std::strncpy(veh.m_display_name, HUD::GET_FILENAME_FOR_AUDIO_CONVERSATION(game_name), sizeof(veh.m_display_name)); std::strncpy(veh.m_display_name, game_name, sizeof(veh.m_display_name));
char vehicle_class[32]; const auto vehicle_class = item.child("vehicleClass").text().as_string();
std::sprintf(vehicle_class, "VEH_CLASS_%i", VEHICLE::GET_VEHICLE_CLASS_FROM_NAME(hash)); constexpr auto enum_prefix_len = 3;
std::strncpy(veh.m_vehicle_class, HUD::GET_FILENAME_FOR_AUDIO_CONVERSATION(vehicle_class), sizeof(veh.m_vehicle_class)); if (std::strlen(vehicle_class) > enum_prefix_len)
std::strncpy(veh.m_vehicle_class, vehicle_class + enum_prefix_len, sizeof(veh.m_vehicle_class));
veh.m_hash = hash; veh.m_hash = hash;
@ -321,8 +337,7 @@ namespace big
std::strncpy(weapon.m_name, name, sizeof(weapon.m_name)); std::strncpy(weapon.m_name, name, sizeof(weapon.m_name));
const auto display_name = HUD::GET_FILENAME_FOR_AUDIO_CONVERSATION(human_name_hash); std::strncpy(weapon.m_display_name, human_name_hash, sizeof(weapon.m_display_name));
std::strncpy(weapon.m_display_name, display_name, sizeof(weapon.m_name));
auto weapon_flags = std::string(item.child("WeaponFlags").text().as_string()); auto weapon_flags = std::string(item.child("WeaponFlags").text().as_string());
@ -391,11 +406,78 @@ namespace big
parse_ped(peds, mapped_peds, doc); parse_ped(peds, mapped_peds, doc);
}); });
} }
else if (std::string str = rpf_wrapper.get_name(); (str.find("componentpeds") != std::string::npos || str.find("streamedpeds") != std::string::npos || str.find("mppatches") != std::string::npos || str.find("cutspeds") != std::string::npos) && file.extension() == ".yft")
{
const auto name = file.stem().string();
const auto hash = rage::joaat(name);
if (std::find(mapped_peds.begin(), mapped_peds.end(), hash) != mapped_peds.end())
continue;
mapped_peds.emplace_back(hash);
auto ped = ped_item{};
std::strncpy(ped.m_name, name.c_str(), sizeof(ped.m_name));
ped.m_hash = hash;
peds.emplace_back(std::move(ped));
}
} }
return files.size(); return files.size();
}); });
if (state() == eGtaDataUpdateState::UPDATING)
{
yim_fipackfile::for_each_fipackfile();
}
else
{
while (state() != eGtaDataUpdateState::ON_INIT_UPDATE_END)
std::this_thread::sleep_for(100ms);
}
static bool translate_lebel = false;
g_fiber_pool->queue_job([&] {
for (auto& item : vehicles)
{
std::strncpy(item.m_display_manufacturer, HUD::GET_FILENAME_FOR_AUDIO_CONVERSATION(item.m_display_manufacturer), sizeof(item.m_display_manufacturer));
std::strncpy(item.m_display_name, HUD::GET_FILENAME_FOR_AUDIO_CONVERSATION(item.m_display_name), sizeof(item.m_display_name));
char vehicle_class[32];
std::sprintf(vehicle_class, "VEH_CLASS_%i", VEHICLE::GET_VEHICLE_CLASS_FROM_NAME(item.m_hash));
std::strncpy(item.m_vehicle_class, HUD::GET_FILENAME_FOR_AUDIO_CONVERSATION(vehicle_class), sizeof(item.m_vehicle_class));
}
for (auto& item : weapons)
{
std::strncpy(item.m_display_name, HUD::GET_FILENAME_FOR_AUDIO_CONVERSATION(item.m_display_name), sizeof(item.m_display_name));
}
for (auto it = peds.begin(); it != peds.end();)
{
if (CPedModelInfo* info = model_info::get_model<CPedModelInfo*>(it->m_hash))
{
static std::array<std::string, 30> ped_types = {"PLAYER_0", "PLAYER_1", "NETWORK_PLAYER", "PLAYER_2", "CIVMALE", "CIVFEMALE", "COP", "GANG_ALBANIAN", "GANG_BIKER_1", "GANG_BIKER_2", "GANG_BIKER_2", "GANG_RUSSIAN", "GANG_RUSSIAN_2", "GANG_RUSSIAN_2", "GANG_JAMAICAN", "GANG_AFRICAN_AMERICAN", "GANG_KOREAN", "GANG_CHINESE_JAPANESE", "GANG_PUERTO_RICAN", "DEALER", "MEDIC", "FIREMAN", "CRIMINAL", "BUM", "PROSTITUTE", "SPECIAL", "MISSION", "SWAT", "ANIMAL", "ARMY"};
std::strncpy(it->m_ped_type, ped_types[info->ped_type].c_str(), sizeof(it->m_ped_type));
++it;
}
else
{
peds.erase(it);
}
}
translate_lebel = true;
});
while (!translate_lebel)
{
if (state() == eGtaDataUpdateState::UPDATING)
script::get_current()->yield();
else
std::this_thread::sleep_for(100ms);
}
m_update_state = eGtaDataUpdateState::IDLE; m_update_state = eGtaDataUpdateState::IDLE;
LOG(INFO) << "Cache has been rebuilt.\n\tPeds: " << peds.size() << "\n\tVehicles: " << vehicles.size() LOG(INFO) << "Cache has been rebuilt.\n\tPeds: " << peds.size() << "\n\tVehicles: " << vehicles.size()
<< "\n\tWeapons: " << weapons.size(); << "\n\tWeapons: " << weapons.size();

View File

@ -12,7 +12,10 @@ namespace big
NEEDS_UPDATE, NEEDS_UPDATE,
WAITING_FOR_SINGLE_PLAYER, WAITING_FOR_SINGLE_PLAYER,
WAITING_FOR_ONLINE, WAITING_FOR_ONLINE,
UPDATING UPDATING,
ON_INIT_WAITING,
ON_INIT_UPDATE_START,
ON_INIT_UPDATE_END
}; };
using ped_map = std::map<std::string, ped_item>; using ped_map = std::map<std::string, ped_item>;
@ -28,8 +31,10 @@ namespace big
bool cache_needs_update() const; bool cache_needs_update() const;
eGtaDataUpdateState state() const; eGtaDataUpdateState state() const;
void set_state(eGtaDataUpdateState state);
void update_in_online(); void update_in_online();
void update_now(); void update_now();
void update_on_init();
const ped_item& ped_by_hash(std::uint32_t hash); const ped_item& ped_by_hash(std::uint32_t hash);
const vehicle_item& vehicle_by_hash(std::uint32_t hash); const vehicle_item& vehicle_by_hash(std::uint32_t hash);

View File

@ -7,7 +7,7 @@ namespace big
{ {
public: public:
char m_name[32]; char m_name[32];
char m_ped_type[16]; char m_ped_type[32];
std::uint32_t m_hash; std::uint32_t m_hash;
}; };
#pragma pack(pop) #pragma pack(pop)

View File

@ -12,7 +12,7 @@ namespace big
this->mount_name = mount_name; this->mount_name = mount_name;
} }
static std::vector<std::string> get_non_dlc_mounted_devices_names() std::vector<std::string> yim_fipackfile::get_non_dlc_mounted_devices_names()
{ {
std::vector<std::string> non_dlc_mounted_devices_names; std::vector<std::string> non_dlc_mounted_devices_names;
@ -37,7 +37,12 @@ namespace big
return non_dlc_mounted_devices_names; return non_dlc_mounted_devices_names;
} }
void yim_fipackfile::for_each_fipackfile(std::function<size_t(yim_fipackfile& rpf_wrapper)> cb) void yim_fipackfile::add_wrapper_call_back(std::function<size_t(yim_fipackfile& rpf_wrapper)> cb)
{
m_wrapper_call_back.push_back(cb);
}
void yim_fipackfile::for_each_fipackfile()
{ {
// the idea is to reuse existing mount points as much as possible because // the idea is to reuse existing mount points as much as possible because
// even when mounting / unmounting properly you'll get file errors // even when mounting / unmounting properly you'll get file errors
@ -79,44 +84,19 @@ namespace big
{ {
size_t acc = 0; size_t acc = 0;
rpf_wrapper.mount_name = "memory:/"; static std::vector<std::string> mount_names = {"memory:/", "memory:", "dlc", "dlc:", "dlc:/", "dlcpacks:/", "common:/", "commoncrc:/", "update:/", "update2:/", "platform:/", "platformcrc:/", "gamecache:/"};
acc += cb(rpf_wrapper);
rpf_wrapper.mount_name = "memory:"; for (auto& mount_name : mount_names)
acc += cb(rpf_wrapper); {
rpf_wrapper.mount_name = mount_name;
rpf_wrapper.mount_name = "dlc"; if (auto count = rpf_wrapper.get_file_paths().size())
acc += cb(rpf_wrapper); {
acc += count;
rpf_wrapper.mount_name = "dlc:"; std::for_each(m_wrapper_call_back.begin(), m_wrapper_call_back.end(), [&rpf_wrapper](std::function<size_t(yim_fipackfile & rpf_wrapper)> cb) {
acc += cb(rpf_wrapper); cb(rpf_wrapper);
});
rpf_wrapper.mount_name = "dlc:/"; }
acc += cb(rpf_wrapper); }
rpf_wrapper.mount_name = "dlcpacks:/";
acc += cb(rpf_wrapper);
rpf_wrapper.mount_name = "common:/";
acc += cb(rpf_wrapper);
rpf_wrapper.mount_name = "commoncrc:/";
acc += cb(rpf_wrapper);
rpf_wrapper.mount_name = "update:/";
acc += cb(rpf_wrapper);
rpf_wrapper.mount_name = "update2:/";
acc += cb(rpf_wrapper);
rpf_wrapper.mount_name = "platform:/";
acc += cb(rpf_wrapper);
rpf_wrapper.mount_name = "platformcrc:/";
acc += cb(rpf_wrapper);
rpf_wrapper.mount_name = "gamecache:/";
acc += cb(rpf_wrapper);
// if we got nothing with those mount points for this rpf, mount it // if we got nothing with those mount points for this rpf, mount it
if (!acc) if (!acc)
@ -124,14 +104,18 @@ namespace big
rpf_wrapper.mount_name = default_mount_name; rpf_wrapper.mount_name = default_mount_name;
rpf->Mount(default_mount_name); rpf->Mount(default_mount_name);
cb(rpf_wrapper); std::for_each(m_wrapper_call_back.begin(), m_wrapper_call_back.end(), [&rpf_wrapper](std::function<size_t(yim_fipackfile & rpf_wrapper)> cb) {
cb(rpf_wrapper);
});
g_pointers->m_fipackfile_unmount(default_mount_name); g_pointers->m_fipackfile_unmount(default_mount_name);
} }
} }
else else
{ {
cb(rpf_wrapper); std::for_each(m_wrapper_call_back.begin(), m_wrapper_call_back.end(), [&rpf_wrapper](std::function<size_t(yim_fipackfile & rpf_wrapper)> cb) {
cb(rpf_wrapper);
});
} }
if (i % yield_increment == 0) if (i % yield_increment == 0)
@ -178,6 +162,11 @@ namespace big
return file_paths; return file_paths;
} }
const char* yim_fipackfile::get_name()
{
return rpf->GetName();
}
void yim_fipackfile::read_file(const std::filesystem::path& path, file_contents_callback&& cb) void yim_fipackfile::read_file(const std::filesystem::path& path, file_contents_callback&& cb)
{ {
if (const auto handle = rpf->Open(path.string().c_str(), true); handle != -1) if (const auto handle = rpf->Open(path.string().c_str(), true); handle != -1)

View File

@ -14,9 +14,18 @@ namespace big
public: public:
explicit yim_fipackfile(rage::fiPackfile* rpf, const std::string& mount_name); explicit yim_fipackfile(rage::fiPackfile* rpf, const std::string& mount_name);
static void for_each_fipackfile(std::function<size_t(yim_fipackfile& rpf_wrapper)> cb); static std::vector<std::string> get_non_dlc_mounted_devices_names();
static inline std::vector<std::function<size_t(yim_fipackfile& rpf_wrapper)>> m_wrapper_call_back;
static void add_wrapper_call_back(std::function<size_t(yim_fipackfile& rpf_wrapper)> cb);
static void for_each_fipackfile();
std::vector<std::filesystem::path> get_file_paths(std::string parent = {}); std::vector<std::filesystem::path> get_file_paths(std::string parent = {});
const char* get_name();
void read_file(const std::filesystem::path& path, file_contents_callback&& cb); void read_file(const std::filesystem::path& path, file_contents_callback&& cb);
void read_xml_file(const std::filesystem::path& path, std::function<void(pugi::xml_document& doc)> cb); void read_xml_file(const std::filesystem::path& path, std::function<void(pugi::xml_document& doc)> cb);

View File

@ -680,4 +680,4 @@ namespace big::vehicle
g.m_remote_controlled_vehicle = veh; g.m_remote_controlled_vehicle = veh;
return true; return true;
} }
} }

View File

@ -46,6 +46,14 @@ namespace big
{ {
g_gta_data_service->update_in_online(); g_gta_data_service->update_in_online();
} }
if (*g_pointers->m_game_state == eGameState::Respawn)
{
if (ImGui::Button("GAME_CACHE_ON_INIT"_T.data()))
{
g_gta_data_service->update_on_init();
}
}
} }
break; break;
@ -68,6 +76,18 @@ namespace big
break; break;
} }
case eGtaDataUpdateState::ON_INIT_WAITING:
{
ImGui::Text("GAME_CACHE_WAITING_FOR_SINGLE_PLAYER"_T.data());
break;
}
case eGtaDataUpdateState::ON_INIT_UPDATE_START:
{
ImGui::Text("GAME_CACHE_UPDATING"_T.data());
break;
}
case eGtaDataUpdateState::IDLE: case eGtaDataUpdateState::IDLE:
{ {
ImGui::CloseCurrentPopup(); ImGui::CloseCurrentPopup();