Fix GTA data service (#1635)

* fix(gta_data): service now parses unloaded RPF files
This commit is contained in:
maybegreat48 2023-07-07 05:57:38 +00:00 committed by GitHub
parent ac302d2bbb
commit c121e72eb6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 302 additions and 445 deletions

View File

@ -212,10 +212,9 @@ namespace big
reaction request_control_event{"Request Control Event", "Blocked Request Control Event from %s", "%s tried to mess with my vehicle!"};
reaction report{"Report", "Blocked Report from %s", "%s tried to report me!"};
interloper_reaction breakup_others{"Breakup Kicks On Other Players", "%s is trying to breakup kick %s!", "%s is trying to breakup kick %s!", true, true}; // blockable only when host but we have no way to specify that atm
reaction gamer_instruction_kick{"Gamer Instruction Kick", "Blocked Gamer Instruction Kick from %s", "%s tried to kick me out!"};
NLOHMANN_DEFINE_TYPE_INTRUSIVE(reactions, bounty, ceo_money, ceo_kick, clear_wanted_level, crash, end_session_kick, fake_deposit, force_mission, force_teleport, gta_banner, kick_from_interior, mc_teleport, network_bail, personal_vehicle_destroyed, remote_off_radar, rotate_cam, send_to_cutscene, send_to_location, sound_spam, spectate_notification, give_collectible, transaction_error, tse_freeze, tse_sender_mismatch, vehicle_kick, teleport_to_warehouse, trigger_business_raid, start_activity, start_script, null_function_kick, destroy_personal_vehicle, clear_ped_tasks, turn_into_beast, remote_wanted_level, remote_wanted_level_others, remote_ragdoll, kick_vote, report_cash_spawn, modder_detection, request_control_event, report, breakup_others, gamer_instruction_kick)
NLOHMANN_DEFINE_TYPE_INTRUSIVE(reactions, bounty, ceo_money, ceo_kick, clear_wanted_level, crash, end_session_kick, fake_deposit, force_mission, force_teleport, gta_banner, kick_from_interior, mc_teleport, network_bail, personal_vehicle_destroyed, remote_off_radar, rotate_cam, send_to_cutscene, send_to_location, sound_spam, spectate_notification, give_collectible, transaction_error, tse_freeze, tse_sender_mismatch, vehicle_kick, teleport_to_warehouse, trigger_business_raid, start_activity, start_script, null_function_kick, destroy_personal_vehicle, clear_ped_tasks, turn_into_beast, remote_wanted_level, remote_wanted_level_others, remote_ragdoll, kick_vote, report_cash_spawn, modder_detection, request_control_event, report, gamer_instruction_kick)
} reactions{};
struct player
@ -772,7 +771,7 @@ namespace big
bool show_infinite_mag = false;
bool show_aimbot = false;
bool show_triggerbot = false;
bool show_invisibility = false;
bool show_invisibility = false;
NLOHMANN_DEFINE_TYPE_INTRUSIVE(ingame_overlay_indicators, show_player_godmode, show_off_radar, show_vehicle_godmode, show_never_wanted, show_always_full_ammo, show_infinite_ammo, show_infinite_mag, show_aimbot, show_triggerbot, show_invisibility)
} ingame_overlay_indicators{};

View File

@ -89,9 +89,11 @@ namespace big::functions
using fidevice_get_device = rage::fiDevice* (*)(const char* path, bool allow_root);
using fipackfile_ctor = rage::fiPackfile* (*)(rage::fiPackfile* this_);
using fipackfile_dtor = rage::fiPackfile* (*)(rage::fiPackfile* this_);
using fipackfile_open_archive = bool (*)(rage::fiPackfile* this_, const char* archive, bool b_true, int type, intptr_t very_false);
using fipackfile_mount = bool (*)(rage::fiPackfile* this_, const char* mount_point);
using fipackfile_unmount = bool (*)(const char* mount_point);
using fipackfile_mount = bool (*)(rage::fiPackfile* this_, const char* mount_point);
using fipackfile_unmount = bool (*)(const char* mount_point);
using fipackfile_close_archive = void (*)(rage::fiDevice* this_);
using get_gamer_online_state = bool (*)(int profile_index, rage::rlGamerHandle* handles, std::uint32_t count, int* online_state, rage::rlTaskStatus* status);
using start_get_session_by_gamer_handle = bool (*)(int profile_index, rage::rlGamerHandle* handles, int count, rage::rlSessionByGamerTaskResult* result, int unk, bool* success, rage::rlTaskStatus* state);

View File

@ -13,12 +13,9 @@ namespace rage
{
}
fiDeviceImplemented::~fiDeviceImplemented()
{
}
fiDevice::~fiDevice()
void fiDeviceImplemented::Destroy()
{
LOG(FATAL) << "pure fiDevice call (" __FUNCTION__ ")";
}
uint64_t fiDeviceImplemented::Open(const char* fileName, bool)
@ -256,6 +253,11 @@ namespace rage
big::g_pointers->m_gta.m_fipackfile_ctor(this);
}
fiPackfile::~fiPackfile()
{
big::g_pointers->m_gta.m_fipackfile_dtor(this);
}
bool fiPackfile::OpenPackfile(const char* archive, bool b_true, int type, intptr_t very_false)
{
return big::g_pointers->m_gta.m_fipackfile_open_archive(this, archive, b_true, type, very_false);
@ -266,6 +268,11 @@ namespace rage
return big::g_hooking->get_original<big::hooks::fipackfile_mount>()(this, mount_point);
}
void fiPackfile::ClosePackfile()
{
big::g_pointers->m_gta.m_fipackfile_close_archive(this);
}
void fiDevice::Unmount(const char* rootPath)
{
big::g_pointers->m_gta.m_fipackfile_unmount(rootPath);

View File

@ -33,102 +33,57 @@ namespace rage
}
static bool MountGlobal(const char* mountPoint, fiDevice* device, bool allowRoot);
static void Unmount(const char* rootPath);
static void Unmount(fiDevice const& device);
public:
virtual ~fiDevice() = 0;
virtual uint64_t Open(const char* fileName, bool readOnly) = 0;
virtual uint64_t OpenBulk(const char* fileName, uint64_t* ptr) = 0;
virtual uint64_t OpenBulkWrap(const char* fileName, uint64_t* ptr, void*) = 0;
virtual uint64_t CreateLocal(const char* fileName) = 0;
virtual uint64_t Create(const char* fileName) = 0;
virtual uint32_t Read(uint64_t handle, void* buffer, uint32_t toRead) = 0;
virtual void Destroy() = 0;
virtual uint64_t Open(const char* fileName, bool readOnly) = 0;
virtual uint64_t OpenBulk(const char* fileName, uint64_t* ptr) = 0;
virtual uint64_t OpenBulkWrap(const char* fileName, uint64_t* ptr, void*) = 0;
virtual uint64_t CreateLocal(const char* fileName) = 0;
virtual uint64_t Create(const char* fileName) = 0;
virtual uint32_t Read(uint64_t handle, void* buffer, uint32_t toRead) = 0;
virtual uint32_t ReadBulk(uint64_t handle, uint64_t ptr, void* buffer, uint32_t toRead) = 0;
virtual uint32_t WriteBulk(uint64_t, int, int, int, int) = 0;
virtual uint32_t Write(uint64_t, void*, int) = 0;
virtual uint32_t Seek(uint64_t handle, int32_t distance, uint32_t method) = 0;
virtual uint64_t SeekLong(uint64_t handle, int64_t distance, uint32_t method) = 0;
virtual int32_t Close(uint64_t handle) = 0;
virtual int32_t CloseBulk(uint64_t handle) = 0;
virtual int GetFileLength(uint64_t handle) = 0;
virtual uint64_t GetFileLengthUInt64(uint64_t handle) = 0;
// dummy!
virtual int m_40(int) = 0;
virtual bool RemoveFile(const char* file) = 0;
virtual int RenameFile(const char* from, const char* to) = 0;
virtual int CreateDirectory(const char* dir) = 0;
virtual int RemoveDirectory(const char* dir) = 0;
virtual void m_xx() = 0;
virtual uint64_t GetFileLengthLong(const char* fileName) = 0;
virtual uint64_t GetFileTime(const char* file) = 0;
virtual bool SetFileTime(const char* file, FILETIME fileTime) = 0;
virtual uint64_t FindFirst(const char* path, fiFindData* findData) = 0;
virtual bool FindNext(uint64_t handle, fiFindData* findData) = 0;
virtual int FindClose(uint64_t handle) = 0;
virtual rage::fiDevice* GetUnkDevice() = 0;
virtual void* m_xy(void*, int, void*) = 0;
virtual bool Truncate(uint64_t handle) = 0;
virtual uint32_t GetFileAttributes(const char* path) = 0;
virtual bool m_xz() = 0;
virtual bool SetFileAttributes(const char* file, uint32_t FileAttributes) = 0;
virtual int m_yx() = 0;
// read even if read() returns less than length
virtual bool ReadFull(uint64_t handle, void* buffer, uint32_t length) = 0;
virtual bool WriteFull(uint64_t handle, void* buffer, uint32_t length) = 0;
virtual int32_t GetResourceVersion(const char* fileName, ResourceFlags* flags) = 0;
virtual int32_t m_yy() = 0;
virtual int32_t m_yz(void*) = 0;
virtual int32_t m_zx(void*) = 0;// return 0x40000000
virtual bool IsCollection() = 0;
virtual bool m_addedIn1290() = 0;
virtual fiDevice* GetCollection() = 0;// return this
virtual bool m_ax() = 0;
virtual int32_t GetCollectionId() = 0;
virtual const char* GetName() = 0;
virtual uint32_t WriteBulk(uint64_t, int, int, int, int) = 0;
virtual uint32_t Write(uint64_t, void*, int) = 0;
virtual uint32_t Seek(uint64_t handle, int32_t distance, uint32_t method) = 0;
virtual uint64_t SeekLong(uint64_t handle, int64_t distance, uint32_t method) = 0;
virtual int32_t Close(uint64_t handle) = 0;
virtual int32_t CloseBulk(uint64_t handle) = 0;
virtual int GetFileLength(uint64_t handle) = 0;
virtual uint64_t GetFileLengthUInt64(uint64_t handle) = 0;
virtual int m_40(int) = 0;
virtual bool RemoveFile(const char* file) = 0;
virtual int RenameFile(const char* from, const char* to) = 0;
virtual int CreateDirectory(const char* dir) = 0;
virtual int RemoveDirectory(const char* dir) = 0;
virtual void m_xx() = 0;
virtual uint64_t GetFileLengthLong(const char* fileName) = 0;
virtual uint64_t GetFileTime(const char* file) = 0;
virtual bool SetFileTime(const char* file, FILETIME fileTime) = 0;
virtual uint64_t FindFirst(const char* path, fiFindData* findData) = 0;
virtual bool FindNext(uint64_t handle, fiFindData* findData) = 0;
virtual int FindClose(uint64_t handle) = 0;
virtual rage::fiDevice* GetUnkDevice() = 0;
virtual void* m_xy(void*, int, void*) = 0;
virtual bool Truncate(uint64_t handle) = 0;
virtual uint32_t GetFileAttributes(const char* path) = 0;
virtual bool m_xz() = 0;
virtual bool SetFileAttributes(const char* file, uint32_t FileAttributes) = 0;
virtual int m_yx() = 0;
virtual bool ReadFull(uint64_t handle, void* buffer, uint32_t length) = 0;
virtual bool WriteFull(uint64_t handle, void* buffer, uint32_t length) = 0;
virtual int32_t GetResourceVersion(const char* fileName, ResourceFlags* flags) = 0;
virtual int32_t m_yy() = 0;
virtual int32_t m_yz(void*) = 0;
virtual int32_t m_zx(void*) = 0;
virtual bool IsCollection() = 0;
virtual bool m_addedIn1290() = 0;
virtual fiDevice* GetCollection() = 0;
virtual bool m_ax() = 0;
virtual int32_t GetCollectionId() = 0;
virtual const char* GetName() = 0;
};
class fiDeviceImplemented : public fiDevice
@ -137,144 +92,64 @@ namespace rage
fiDeviceImplemented();
public:
virtual ~fiDeviceImplemented();
virtual void Destroy();
virtual uint64_t Open(const char* fileName, bool readOnly);
virtual uint64_t OpenBulk(const char* fileName, uint64_t* ptr);
virtual uint64_t OpenBulkWrap(const char* fileName, uint64_t* ptr, void* a3);
virtual uint64_t CreateLocal(const char* fileName);
virtual uint64_t Create(const char* fileName);
virtual uint32_t Read(uint64_t handle, void* buffer, uint32_t toRead);
virtual uint32_t ReadBulk(uint64_t handle, uint64_t ptr, void* buffer, uint32_t toRead);
virtual uint32_t WriteBulk(uint64_t, int, int, int, int);
virtual uint32_t Write(uint64_t, void*, int);
virtual uint32_t Seek(uint64_t handle, int32_t distance, uint32_t method);
virtual uint64_t SeekLong(uint64_t handle, int64_t distance, uint32_t method);
virtual int32_t Close(uint64_t handle);
virtual int32_t CloseBulk(uint64_t handle);
virtual int GetFileLength(uint64_t handle);
virtual uint64_t GetFileLengthUInt64(uint64_t handle);
// dummy!
virtual int m_40(int);
virtual bool RemoveFile(const char* file);
virtual int RenameFile(const char* from, const char* to);
virtual int CreateDirectory(const char* dir);
virtual int RemoveDirectory(const char* dir);
virtual void m_xx();
virtual uint64_t GetFileLengthLong(const char* fileName);
virtual uint64_t GetFileTime(const char* file);
virtual bool SetFileTime(const char* file, FILETIME fileTime);
virtual uint64_t FindFirst(const char* path, fiFindData* findData);
virtual bool FindNext(uint64_t handle, fiFindData* findData);
virtual int FindClose(uint64_t handle);
virtual rage::fiDevice* GetUnkDevice();
virtual void* m_xy(void* a1, int a2, void* a3);
virtual bool Truncate(uint64_t handle);
virtual uint32_t GetFileAttributes(const char* path);
virtual bool m_xz();
virtual bool SetFileAttributes(const char* file, uint32_t FileAttributes);
virtual int m_yx();
// read even if read() returns less than length
virtual bool ReadFull(uint64_t handle, void* buffer, uint32_t length);
virtual bool WriteFull(uint64_t handle, void* buffer, uint32_t length);
virtual int32_t GetResourceVersion(const char* fileName, ResourceFlags* version);
virtual int32_t m_yy();
virtual int32_t m_yz(void*);
virtual int32_t m_zx(void*);// return 0x40000000
virtual int32_t m_zx(void*); // return 0x40000000
virtual bool IsCollection();
virtual bool m_addedIn1290();
virtual fiDevice* GetCollection();// return this
virtual fiDevice* GetCollection(); // return this
virtual bool m_ax();
virtual int32_t GetCollectionId();
virtual const char* GetName();
};
class fiDeviceRelative : public fiDeviceImplemented
{
private:
char m_pad[272];
public:
fiDeviceRelative();
// any RAGE path can be used; including root-relative paths
void SetPath(const char* relativeTo, rage::fiDevice* baseDevice, bool allowRoot);
// compatibility wrapper for NY code
inline void SetPath(const char* relativeTo, bool allowRoot)
{
SetPath(relativeTo, nullptr, allowRoot);
}
// mounts the device in the device stack
void Mount(const char* mountPoint);
};
class fiEncryptingDevice : public fiDeviceImplemented
{
private:
void* m_keyState;
void* m_0010;
char m_buffer[4096];
bool m_1018;
alignas(int) char m_pad[64];// unsure
private:
void* AllocKeyState(const uint8_t* key);
public:
fiEncryptingDevice(const std::array<uint8_t, 32>& key);
void FreeKeyState();
};
class fiPackfile : public fiDeviceImplemented
{
private:
char m_pad[368 + (0x650 - 0x590)];
char m_pad[368 + (0x650 - 0x590)]{};
public:
fiPackfile();
~fiPackfile();
// any RAGE path can be used; including root-relative paths
bool OpenPackfile(const char* archive, bool bTrue, int type, intptr_t veryFalse);

View File

@ -148,10 +148,12 @@ namespace big
functions::fidevice_get_device m_fidevice_get_device{};
functions::fipackfile_ctor m_fipackfile_ctor{};
functions::fipackfile_dtor m_fipackfile_dtor{};
rage::fiPackfile** m_fipackfile_instances{};
functions::fipackfile_open_archive m_fipackfile_open_archive{};
functions::fipackfile_mount m_fipackfile_mount{};
functions::fipackfile_unmount m_fipackfile_unmount{};
functions::fipackfile_close_archive m_fipackfile_close_archive{};
PVOID m_invalid_mods_crash_detour{};
PVOID m_invalid_decal_crash{};

View File

@ -17,9 +17,13 @@ namespace big
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);
});
const auto files = rpf_wrapper.get_file_paths();
for (const auto& file : files)
{
std::for_each(yim_fipackfile::m_wrapper_call_back.begin(), yim_fipackfile::m_wrapper_call_back.end(), [&rpf_wrapper, file](std::function<void(yim_fipackfile & rpf_wrapper, std::filesystem::path path)> cb) {
cb(rpf_wrapper, file);
});
}
if (!stricmp(this_->GetName(), "BgScript.rpf"))
{

View File

@ -166,71 +166,16 @@ namespace big
}
break;
}
case rage::eNetMessage::MsgRemoveGamersFromSessionCmd:
{
player_ptr pl;
uint64_t session_id;
buffer.ReadQWord(&session_id, 64);
uint32_t count;
buffer.ReadDword(&count, 6);
for (std::uint32_t i = 0; i < count; i++)
{
uint64_t peer_id;
buffer.ReadQWord(&peer_id, 64);
for (std::uint32_t i = 0; i < gta_util::get_network()->m_game_session_ptr->m_peer_count; i++)
{
if (gta_util::get_network()->m_game_session_ptr->m_peers[i]->m_peer_data.m_peer_id_2 == peer_id)
{
pl = g_player_service->get_by_host_token(
gta_util::get_network()->m_game_session_ptr->m_peers[i]->m_peer_data.m_host_token);
break;
}
}
}
if (player && pl && player->id() != pl->id() && count == 1 && frame->m_msg_id == -1)
{
if (g_player_service->get_self()->is_host())
{
g.reactions.breakup_others.process(player, pl);
session::add_infraction(player, Infraction::BREAKUP_KICK_DETECTED);
if (g.reactions.breakup_others.block)
return true;
if (g.reactions.breakup_others.karma)
dynamic_cast<player_command*>(command::get(RAGE_JOAAT("breakup")))->call(player, {});
}
else
{
g.reactions.breakup_others.process(player, pl);
session::add_infraction(player, Infraction::BREAKUP_KICK_DETECTED);
if (g.reactions.breakup_others.karma)
dynamic_cast<player_command*>(command::get(RAGE_JOAAT("breakup")))->call(player, {});
;
}
}
break;
}
case rage::eNetMessage::MsgNetComplaint:
{
uint64_t host_token{};
buffer.ReadQWord(&host_token, 64);
std::vector<CNetGamePlayer*> players;
uint32_t num_of_tokens{};
buffer.ReadDword(&num_of_tokens, 32);
if (player && host_token != player->get_net_data()->m_host_token && !player->exposed_desync_protection)
{
session::add_infraction(player, Infraction::DESYNC_PROTECTION);
player->exposed_desync_protection = true;
}
return true; // block desync kicks as host
return true;
}
case rage::eNetMessage::MsgRequestObjectIds:
{

View File

@ -535,31 +535,25 @@ namespace big
g_pointers->m_gta.m_fipackfile_instances = ptr.add(26).rip().as<rage::fiPackfile**>();
}
},
// fiPackfile open archive
// fiPackfile dtor
{
"FPFOA",
"48 8D 68 98 48 81 EC 40 01 00 00 41 8B F9",
"FPFD",
"48 89 5C 24 08 57 48 83 EC 20 48 8D 05 ? ? ? ? 33 FF 48 8B D9 48 89 01 40 88",
[](memory::handle ptr)
{
g_pointers->m_gta.m_fipackfile_open_archive = ptr.sub(0x18).as<functions::fipackfile_open_archive>();
g_pointers->m_gta.m_fipackfile_dtor = ptr.as<functions::fipackfile_dtor>();
}
},
// fiPackfile mount
// fiPackfile stuff
{
"FPFM",
"84 C0 74 1D 48 85 DB 74 0F 48",
[](memory::handle ptr)
{
g_pointers->m_gta.m_fipackfile_mount = ptr.sub(0x1E).as<functions::fipackfile_mount>();
}
},
// fiPackfile unmount
{
"FPFUM",
"E8 ? ? ? ? 84 C0 74 37 80 3D",
"FPU&FPCA&FPOA&FPM",
"E8 ? ? ? ? 48 8D 0D ? ? ? ? E8 ? ? ? ? 8A 05 ? ? ? ? 48 8D 0D",
[](memory::handle ptr)
{
g_pointers->m_gta.m_fipackfile_unmount = ptr.add(1).rip().as<functions::fipackfile_unmount>();
g_pointers->m_gta.m_fipackfile_close_archive = ptr.add(0xD).rip().as<functions::fipackfile_close_archive>();
g_pointers->m_gta.m_fipackfile_open_archive = ptr.add(0x34).rip().as<functions::fipackfile_open_archive>();
g_pointers->m_gta.m_fipackfile_mount = ptr.add(0x47).rip().as<functions::fipackfile_mount>();
}
},
// Invalid Mods Crash Detour

View File

@ -30,9 +30,9 @@ namespace big
}
gta_data_service::gta_data_service() :
m_peds_cache(g_file_manager->get_project_file("./cache/peds.bin"), 4),
m_vehicles_cache(g_file_manager->get_project_file("./cache/vehicles.bin"), 3),
m_weapons_cache(g_file_manager->get_project_file("./cache/weapons.bin"), 4),
m_peds_cache(g_file_manager->get_project_file("./cache/peds.bin"), 5),
m_vehicles_cache(g_file_manager->get_project_file("./cache/vehicles.bin"), 4),
m_weapons_cache(g_file_manager->get_project_file("./cache/weapons.bin"), 5),
m_update_state(eGtaDataUpdateState::IDLE)
{
if (!is_cache_up_to_date())
@ -264,178 +264,170 @@ namespace big
LOG(INFO) << "Rebuilding cache started...";
yim_fipackfile::add_wrapper_call_back([&](yim_fipackfile& rpf_wrapper) {
const auto files = rpf_wrapper.get_file_paths();
for (const auto& file : files)
yim_fipackfile::add_wrapper_call_back([&](yim_fipackfile& rpf_wrapper, std::filesystem::path path) -> void {
if (path.filename() == "setup2.xml")
{
if (file.filename() == "setup2.xml")
std::string dlc_name;
rpf_wrapper.read_xml_file(path, [&dlc_name](pugi::xml_document& doc) {
const auto item = doc.select_node("/SSetupData/nameHash");
dlc_name = item.node().text().as_string();
});
if (dlc_name == "mpG9EC")
{
std::string dlc_name;
rpf_wrapper.read_xml_file(file, [&dlc_name](pugi::xml_document& doc) {
const auto item = doc.select_node("/SSetupData/nameHash");
dlc_name = item.node().text().as_string();
});
if (dlc_name == "mpG9EC")
{
LOG(VERBOSE) << "Bad DLC, skipping...";
return std::size_t(0);
}
}
else if (file.filename() == "vehicles.meta")
{
rpf_wrapper.read_xml_file(file, [&exists, &vehicles, &mapped_vehicles](pugi::xml_document& doc) {
const auto& items = doc.select_nodes("/CVehicleModelInfo__InitDataList/InitDatas/Item");
for (const auto& item_node : items)
{
const auto item = item_node.node();
const auto name = item.child("modelName").text().as_string();
const auto hash = rage::joaat(name);
if (exists(mapped_vehicles, hash))
continue;
mapped_vehicles.emplace_back(hash);
auto veh = vehicle_item{};
std::strncpy(veh.m_name, name, sizeof(veh.m_name));
const auto manufacturer_display = item.child("vehicleMakeName").text().as_string();
std::strncpy(veh.m_display_manufacturer, manufacturer_display, sizeof(veh.m_display_manufacturer));
const auto game_name = item.child("gameName").text().as_string();
std::strncpy(veh.m_display_name, game_name, sizeof(veh.m_display_name));
const auto vehicle_class = item.child("vehicleClass").text().as_string();
constexpr auto enum_prefix_len = 3;
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;
vehicles.emplace_back(std::move(veh));
}
});
}
else if (const auto file_str = file.string(); file_str.find("weapon") != std::string::npos && file.extension() == ".meta")
{
rpf_wrapper.read_xml_file(file, [&exists, &weapons, &mapped_weapons](pugi::xml_document& doc) {
const auto& items = doc.select_nodes("/CWeaponInfoBlob/Infos/Item/Infos/Item[@type='CWeaponInfo']");
for (const auto& item_node : items)
{
const auto item = item_node.node();
const auto name = item.child("Name").text().as_string();
const auto hash = rage::joaat(name);
if (hash == RAGE_JOAAT("WEAPON_BIRD_CRAP"))
continue;
if (exists(mapped_weapons, hash))
continue;
mapped_weapons.emplace_back(hash);
const auto human_name_hash = item.child("HumanNameHash").text().as_string();
if (std::strcmp(human_name_hash, "WT_INVALID") == 0 || std::strcmp(human_name_hash, "WT_VEHMINE") == 0)
continue;
auto weapon = weapon_item{};
std::strncpy(weapon.m_name, name, sizeof(weapon.m_name));
std::strncpy(weapon.m_display_name, human_name_hash, sizeof(weapon.m_display_name));
auto weapon_flags = std::string(item.child("WeaponFlags").text().as_string());
bool is_gun = false;
bool is_rechargable = false;
const char* category = "";
std::size_t pos;
while ((pos = weapon_flags.find(' ')) != std::string::npos)
{
const auto flag = weapon_flags.substr(0, pos);
if (flag == "Thrown")
{
weapon.m_throwable = true;
}
else if (flag == "Gun")
{
is_gun = true;
}
else if (flag == "DisplayRechargeTimeHUD")
{
is_rechargable = true;
}
else if (flag == "Vehicle" || flag == "HiddenFromWeaponWheel" || flag == "NotAWeapon")
{
goto skip;
}
weapon_flags.erase(0, pos + 1);
}
category = item.child("Group").text().as_string();
if (std::strlen(category) == 0 || std::strcmp(category, "GROUP_DIGISCANNER") == 0)
continue;
if (std::strlen(category) > 6)
{
std::strncpy(weapon.m_weapon_type, category + 6, sizeof(weapon.m_weapon_type));
}
if (is_gun || !std::strcmp(weapon.m_weapon_type, "MELEE") || !std::strcmp(weapon.m_weapon_type, "UNARMED"))
{
const std::string reward_prefix = "REWARD_";
weapon.m_reward_hash = rage::joaat(reward_prefix + name);
if (is_gun && !is_rechargable)
{
std::string weapon_id = name + 7;
weapon.m_reward_ammo_hash = rage::joaat(reward_prefix + "AMMO_" + weapon_id);
}
}
weapon.m_hash = hash;
weapons.emplace_back(std::move(weapon));
skip:
continue;
}
});
}
else if (file.filename() == "peds.meta")
{
rpf_wrapper.read_xml_file(file, [&exists, &peds, &mapped_peds](pugi::xml_document& 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 (is_crash_ped(hash))
continue;
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));
LOG(VERBOSE) << "Bad DLC, skipping...";
}
}
else if (path.filename() == "vehicles.meta")
{
rpf_wrapper.read_xml_file(path, [&exists, &vehicles, &mapped_vehicles](pugi::xml_document& doc) {
const auto& items = doc.select_nodes("/CVehicleModelInfo__InitDataList/InitDatas/Item");
for (const auto& item_node : items)
{
const auto item = item_node.node();
return files.size();
const auto name = item.child("modelName").text().as_string();
const auto hash = rage::joaat(name);
if (exists(mapped_vehicles, hash))
continue;
mapped_vehicles.emplace_back(hash);
auto veh = vehicle_item{};
std::strncpy(veh.m_name, name, sizeof(veh.m_name));
const auto manufacturer_display = item.child("vehicleMakeName").text().as_string();
std::strncpy(veh.m_display_manufacturer, manufacturer_display, sizeof(veh.m_display_manufacturer));
const auto game_name = item.child("gameName").text().as_string();
std::strncpy(veh.m_display_name, game_name, sizeof(veh.m_display_name));
const auto vehicle_class = item.child("vehicleClass").text().as_string();
constexpr auto enum_prefix_len = 3;
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;
vehicles.emplace_back(std::move(veh));
}
});
}
else if (const auto file_str = path.string(); file_str.find("weapon") != std::string::npos && path.extension() == ".meta")
{
rpf_wrapper.read_xml_file(path, [&exists, &weapons, &mapped_weapons](pugi::xml_document& doc) {
const auto& items = doc.select_nodes("/CWeaponInfoBlob/Infos/Item/Infos/Item[@type='CWeaponInfo']");
for (const auto& item_node : items)
{
const auto item = item_node.node();
const auto name = item.child("Name").text().as_string();
const auto hash = rage::joaat(name);
if (hash == RAGE_JOAAT("WEAPON_BIRD_CRAP"))
continue;
if (exists(mapped_weapons, hash))
continue;
mapped_weapons.emplace_back(hash);
const auto human_name_hash = item.child("HumanNameHash").text().as_string();
if (std::strcmp(human_name_hash, "WT_INVALID") == 0 || std::strcmp(human_name_hash, "WT_VEHMINE") == 0)
continue;
auto weapon = weapon_item{};
std::strncpy(weapon.m_name, name, sizeof(weapon.m_name));
std::strncpy(weapon.m_display_name, human_name_hash, sizeof(weapon.m_display_name));
auto weapon_flags = std::string(item.child("WeaponFlags").text().as_string());
bool is_gun = false;
bool is_rechargable = false;
const char* category = "";
std::size_t pos;
while ((pos = weapon_flags.find(' ')) != std::string::npos)
{
const auto flag = weapon_flags.substr(0, pos);
if (flag == "Thrown")
{
weapon.m_throwable = true;
}
else if (flag == "Gun")
{
is_gun = true;
}
else if (flag == "DisplayRechargeTimeHUD")
{
is_rechargable = true;
}
else if (flag == "Vehicle" || flag == "HiddenFromWeaponWheel" || flag == "NotAWeapon")
{
goto skip;
}
weapon_flags.erase(0, pos + 1);
}
category = item.child("Group").text().as_string();
if (std::strlen(category) == 0 || std::strcmp(category, "GROUP_DIGISCANNER") == 0)
continue;
if (std::strlen(category) > 6)
{
std::strncpy(weapon.m_weapon_type, category + 6, sizeof(weapon.m_weapon_type));
}
if (is_gun || !std::strcmp(weapon.m_weapon_type, "MELEE") || !std::strcmp(weapon.m_weapon_type, "UNARMED"))
{
const std::string reward_prefix = "REWARD_";
weapon.m_reward_hash = rage::joaat(reward_prefix + name);
if (is_gun && !is_rechargable)
{
std::string weapon_id = name + 7;
weapon.m_reward_ammo_hash = rage::joaat(reward_prefix + "AMMO_" + weapon_id);
}
}
weapon.m_hash = hash;
weapons.emplace_back(std::move(weapon));
skip:
continue;
}
});
}
else if (path.filename() == "peds.meta")
{
rpf_wrapper.read_xml_file(path, [&exists, &peds, &mapped_peds](pugi::xml_document& 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) && path.extension() == ".yft")
{
const auto name = path.stem().string();
const auto hash = rage::joaat(name);
if (is_crash_ped(hash))
return;
if (std::find(mapped_peds.begin(), mapped_peds.end(), hash) != mapped_peds.end())
return;
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));
}
});
if (state() == eGtaDataUpdateState::UPDATING)

View File

@ -8,30 +8,67 @@ namespace big
{
yim_fipackfile::yim_fipackfile(rage::fiPackfile* rpf, const std::string& mount_name)
{
this->rpf = rpf;
this->rpf = rpf;
this->mount_name = mount_name;
}
void yim_fipackfile::add_wrapper_call_back(std::function<size_t(yim_fipackfile& rpf_wrapper)> cb)
void yim_fipackfile::add_wrapper_call_back(std::function<void(yim_fipackfile& rpf_wrapper, std::filesystem::path path)> cb)
{
m_wrapper_call_back.push_back(cb);
}
void yim_fipackfile::for_each_fipackfile()
void yim_fipackfile::traverse_rpf_file(const std::string& path, int depth)
{
for (int i = 1; i < 3672; i++) // fipackfile ctor start with 1
std::string mount_path = std::format("temp{}:/", depth);
rage::fiPackfile packfile;
packfile.OpenPackfile(path.c_str(), true, 0, 0);
packfile.Mount(mount_path.c_str());
yim_fipackfile rpf_wrapper = yim_fipackfile(&packfile, mount_path);
const auto files = rpf_wrapper.get_file_paths();
for (const auto& file : files)
{
auto* rpf = g_pointers->m_gta.m_fipackfile_instances[i];
if (rpf)
if (file.extension() == ".rpf")
{
yim_fipackfile rpf_wrapper = yim_fipackfile(rpf);
if (auto handle = ((rage::fiDevice*)&packfile)->Open(file.string().c_str(), true))
{
uint32_t encryption_type{};
((rage::fiDevice*)&packfile)->Seek(handle, 12, 0);
((rage::fiDevice*)&packfile)->Read(handle, &encryption_type, 4);
((rage::fiDevice*)&packfile)->Close(handle);
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 (encryption_type == 0xFFFFFF9)
continue; // skip AES encrypted RPFs
traverse_rpf_file(file.string(), depth + 1);
}
}
else
{
std::for_each(yim_fipackfile::m_wrapper_call_back.begin(), yim_fipackfile::m_wrapper_call_back.end(), [&rpf_wrapper, file](std::function<void(yim_fipackfile & rpf_wrapper, std::filesystem::path path)> cb) {
cb(rpf_wrapper, file);
});
}
}
packfile.Unmount(mount_path.c_str());
packfile.ClosePackfile();
}
void yim_fipackfile::for_each_fipackfile()
{
for (auto& entry : std::filesystem::recursive_directory_iterator(std::filesystem::current_path()))
{
auto rel_path = std::filesystem::relative(entry.path());
if (rel_path.string().contains("mods"))
continue;
if (rel_path.extension() == ".rpf")
traverse_rpf_file(rel_path.string());
}
}
std::vector<std::filesystem::path> yim_fipackfile::get_file_paths(std::string parent)
@ -50,7 +87,7 @@ namespace big
{
std::string fn;
if (parent == "/")
if (parent == mount_name)
fn = std::string(parent.c_str()) + std::string(findData.fileName);
else
fn = std::string(parent.c_str()) + std::string("/") + std::string(findData.fileName);

View File

@ -13,10 +13,11 @@ namespace big
public:
explicit yim_fipackfile(rage::fiPackfile* rpf, const std::string& mount_name = "/");
static inline std::vector<std::function<size_t(yim_fipackfile& rpf_wrapper)>> m_wrapper_call_back;
static inline std::vector<std::function<void(yim_fipackfile& rpf_wrapper, std::filesystem::path path)>> m_wrapper_call_back;
static void add_wrapper_call_back(std::function<size_t(yim_fipackfile& rpf_wrapper)> cb);
static void add_wrapper_call_back(std::function<void(yim_fipackfile& rpf_wrapper, std::filesystem::path path)> cb);
static void traverse_rpf_file(const std::string& path, int depth = 0);
static void for_each_fipackfile();
std::vector<std::filesystem::path> get_file_paths(std::string parent = {});

View File

@ -100,7 +100,6 @@ namespace big
draw_reaction(g.reactions.request_control_event);
ImGui::Separator();
draw_reaction(g.reactions.gamer_instruction_kick);
draw_interloper_reaction(g.reactions.breakup_others);
components::title("SETTINGS_NOTIFICATIONS"_T);
components::sub_title("SETTINGS_NOTIFY_GTA_THREADS"_T);