feat(RCS): Improved crash protections. (#407)
Co-authored-by: Yimura <24669514+Yimura@users.noreply.github.com>
This commit is contained in:
parent
5f70975ffe
commit
abdb88f68a
@ -46,9 +46,13 @@ namespace big::functions
|
|||||||
//Sync signatures START
|
//Sync signatures START
|
||||||
using get_sync_type_info = const char*(*)(uint16_t sync_type, char a2);
|
using get_sync_type_info = const char*(*)(uint16_t sync_type, char a2);
|
||||||
|
|
||||||
using get_sync_tree_for_type = int64_t(*)(CNetworkObjectMgr* mgr, uint16_t sync_type);
|
using get_sync_tree_for_type = rage::netSyncTree*(*)(CNetworkObjectMgr* mgr, uint16_t sync_type);
|
||||||
|
|
||||||
using get_net_object = rage::netObject*(*)(CNetworkObjectMgr* mgr, int16_t id, bool unk3);
|
using get_net_object = rage::netObject*(*)(CNetworkObjectMgr* mgr, int16_t id, bool can_delete_be_pending);
|
||||||
|
|
||||||
|
using get_net_object_for_player = rage::netObject*(*)(CNetworkObjectMgr*, int16_t, CNetGamePlayer*, bool);
|
||||||
|
|
||||||
|
using read_bitbuffer_into_sync_tree = void(*)(rage::netSyncTree* tree, uint64_t flag, uint32_t flag2, rage::datBitBuffer* buffer, uint64_t netLogStub);
|
||||||
//Sync signatures END
|
//Sync signatures END
|
||||||
|
|
||||||
using reset_network_complaints = void(*)(CNetComplaintMgr* mgr);
|
using reset_network_complaints = void(*)(CNetComplaintMgr* mgr);
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
|
#pragma once
|
||||||
#include "node_list.hpp"
|
#include "node_list.hpp"
|
||||||
#include "enums.hpp"
|
#include "enums.hpp"
|
||||||
#include "..\pointers.hpp"
|
#include "../pointers.hpp"
|
||||||
#include "replay.hpp"
|
#include "replay.hpp"
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
namespace rage
|
namespace rage
|
||||||
{
|
{
|
||||||
@ -15,16 +15,6 @@ namespace rage
|
|||||||
char pad_0010[256]; //0x0010
|
char pad_0010[256]; //0x0010
|
||||||
}; //Size: 0x0110
|
}; //Size: 0x0110
|
||||||
|
|
||||||
class CPlayerAppearanceDataNode
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
char pad_0000[24]; //0x0000
|
|
||||||
CPlayerSyncTree* sync_tree; //0x0018
|
|
||||||
char pad_0020[992]; //0x0020
|
|
||||||
uint32_t model; //0x0400
|
|
||||||
char pad_0404[124]; //0x0404
|
|
||||||
}; //Size: 0x0480
|
|
||||||
|
|
||||||
class CNetworkSyncDataULBase
|
class CNetworkSyncDataULBase
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -64,149 +54,7 @@ namespace rage
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class netSyncTree
|
class netObject;
|
||||||
{
|
|
||||||
public:
|
|
||||||
char pad_0000[48]; //0x0000
|
|
||||||
class netSyncTreeNode* m_sync_tree_node; //0x0030
|
|
||||||
}; //Size: 0x0038
|
|
||||||
|
|
||||||
class netSyncTreeNode
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
char pad_0000[192]; //0x0000
|
|
||||||
uint32_t m_player_model; //0x00C0
|
|
||||||
uint32_t m_ped_model; //0x00C4
|
|
||||||
uint32_t m_vehicle_model; //0x00C8
|
|
||||||
char pad_00CC[84]; //0x00CC
|
|
||||||
uint32_t m_pickup_model; //0x0120
|
|
||||||
char pad_0124[44]; //0x0124
|
|
||||||
uint32_t m_object_model; //0x0150
|
|
||||||
char pad_0154[692]; //0x0154
|
|
||||||
}; //Size: 0x0408
|
|
||||||
|
|
||||||
class netObject
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
int16_t object_type; //0x0008
|
|
||||||
int16_t object_id; //0x000A
|
|
||||||
char pad_000C[61]; //0x000C
|
|
||||||
int8_t owner_id; //0x0049
|
|
||||||
int8_t control_id; //0x004A
|
|
||||||
int8_t next_owner_id; //0x004B
|
|
||||||
bool is_remote; //0x004C
|
|
||||||
bool wants_to_delete; //0x004D
|
|
||||||
char pad_004E[1]; //0x004E
|
|
||||||
bool should_not_be_deleted; //0x004F
|
|
||||||
char pad_0050[32]; //0x0050
|
|
||||||
uint32_t players_acked; //0x0070
|
|
||||||
char pad_0074[116]; //0x0074
|
|
||||||
|
|
||||||
virtual ~netObject() = 0;
|
|
||||||
|
|
||||||
virtual void m_8() = 0;
|
|
||||||
virtual void m_10() = 0;
|
|
||||||
virtual void m_18() = 0;
|
|
||||||
virtual void* m_20() = 0;
|
|
||||||
virtual void m_28() = 0;
|
|
||||||
virtual netSyncTree* GetSyncTree() = 0;
|
|
||||||
virtual void m_38() = 0;
|
|
||||||
virtual void m_40() = 0;
|
|
||||||
virtual void m_48() = 0;
|
|
||||||
virtual void m_50() = 0;
|
|
||||||
virtual void m_58() = 0;
|
|
||||||
virtual void m_60() = 0;
|
|
||||||
virtual void m_68() = 0;
|
|
||||||
virtual void m_70() = 0;
|
|
||||||
virtual void m_78() = 0;
|
|
||||||
virtual rage::CObject* GetGameObject() = 0;
|
|
||||||
virtual void m_88() = 0;
|
|
||||||
virtual void m_90() = 0;
|
|
||||||
virtual void m_98() = 0;
|
|
||||||
virtual int GetObjectFlags() = 0;
|
|
||||||
virtual void m_A8() = 0;
|
|
||||||
virtual void m_B0() = 0;
|
|
||||||
virtual void m_B8() = 0;
|
|
||||||
virtual void m_C0() = 0;
|
|
||||||
virtual void m_C8() = 0;
|
|
||||||
virtual int GetSyncFrequency() = 0;
|
|
||||||
virtual void m_D8() = 0;
|
|
||||||
virtual void m_E0() = 0;
|
|
||||||
virtual void m_E8() = 0;
|
|
||||||
virtual void m_F0() = 0;
|
|
||||||
virtual void m_F8() = 0;
|
|
||||||
virtual void Update() = 0;
|
|
||||||
virtual bool m_108_1604() = 0; // added in 1604
|
|
||||||
virtual void m_108() = 0;
|
|
||||||
virtual void m_110() = 0;
|
|
||||||
virtual void m_118() = 0;
|
|
||||||
virtual void m_120() = 0;
|
|
||||||
virtual void m_128() = 0;
|
|
||||||
virtual void m_130() = 0;
|
|
||||||
virtual void m_138() = 0;
|
|
||||||
virtual void m_140() = 0;
|
|
||||||
virtual void m_148() = 0;
|
|
||||||
virtual void m_150() = 0;
|
|
||||||
virtual bool m_158(void* player, int type, int* outReason) = 0;
|
|
||||||
virtual void m_160() = 0;
|
|
||||||
virtual bool m_168(int* outReason) = 0;
|
|
||||||
virtual void m_170() = 0;
|
|
||||||
virtual void m_178() = 0;
|
|
||||||
virtual void m_180() = 0;
|
|
||||||
virtual void m_188() = 0;
|
|
||||||
virtual void m_190() = 0;
|
|
||||||
virtual void m_198() = 0;
|
|
||||||
virtual void m_1A0() = 0;
|
|
||||||
virtual void m_1A8() = 0;
|
|
||||||
virtual void m_1B0() = 0;
|
|
||||||
virtual void m_1B8() = 0;
|
|
||||||
virtual void m_1C0() = 0;
|
|
||||||
virtual void m_1C8() = 0;
|
|
||||||
virtual void m_1D0() = 0;
|
|
||||||
virtual void m_1D8() = 0;
|
|
||||||
virtual void m_1E0() = 0;
|
|
||||||
virtual void m_1E8() = 0;
|
|
||||||
virtual void m_1F0() = 0;
|
|
||||||
virtual void m_1F8() = 0;
|
|
||||||
virtual void m_200() = 0;
|
|
||||||
virtual void m_208() = 0;
|
|
||||||
virtual void m_210() = 0;
|
|
||||||
virtual void m_218() = 0;
|
|
||||||
virtual void m_220() = 0;
|
|
||||||
virtual void m_228() = 0;
|
|
||||||
virtual void m_230() = 0;
|
|
||||||
virtual void m_238() = 0;
|
|
||||||
virtual void m_240() = 0;
|
|
||||||
virtual void m_248() = 0;
|
|
||||||
virtual void m_250() = 0;
|
|
||||||
virtual void m_258() = 0;
|
|
||||||
virtual void m_260() = 0;
|
|
||||||
virtual void m_268() = 0;
|
|
||||||
virtual void m_270() = 0;
|
|
||||||
virtual void m_278() = 0;
|
|
||||||
virtual void m_280() = 0;
|
|
||||||
virtual void m_288() = 0;
|
|
||||||
virtual void m_290() = 0;
|
|
||||||
virtual void m_298() = 0;
|
|
||||||
virtual void m_2A0() = 0;
|
|
||||||
virtual void m_2A8() = 0;
|
|
||||||
virtual void m_2B0() = 0;
|
|
||||||
virtual void m_2B8() = 0;
|
|
||||||
virtual void m_2C0() = 0;
|
|
||||||
virtual void m_2C8() = 0;
|
|
||||||
virtual void m_2D0() = 0;
|
|
||||||
virtual void m_2D8() = 0;
|
|
||||||
virtual void m_2E0() = 0;
|
|
||||||
virtual void m_2E8() = 0;
|
|
||||||
virtual void m_2F0() = 0;
|
|
||||||
virtual void m_2F8() = 0;
|
|
||||||
virtual void m_300() = 0;
|
|
||||||
virtual void m_308() = 0;
|
|
||||||
virtual void m_310() = 0;
|
|
||||||
virtual void m_318() = 0;
|
|
||||||
virtual void m_320() = 0;
|
|
||||||
virtual void UpdatePendingVisibilityChanges() = 0;
|
|
||||||
};
|
|
||||||
class CNetGamePlayer;
|
class CNetGamePlayer;
|
||||||
|
|
||||||
class netObjectMgrBase
|
class netObjectMgrBase
|
||||||
@ -265,6 +113,6 @@ class CNetworkObjectMgr : public rage::netObjectMgrBase
|
|||||||
public:
|
public:
|
||||||
rage::netObject* find_object_by_id(std::uint16_t object_id, bool can_delete_be_pending)
|
rage::netObject* find_object_by_id(std::uint16_t object_id, bool can_delete_be_pending)
|
||||||
{
|
{
|
||||||
return big::g_pointers->m_find_object_by_id(this, object_id, can_delete_be_pending);
|
return big::g_pointers->m_get_net_object(this, object_id, can_delete_be_pending);
|
||||||
};
|
}
|
||||||
};
|
};
|
@ -1,9 +1,24 @@
|
|||||||
#include "hooking.hpp"
|
#include "hooking.hpp"
|
||||||
#include "core/globals.hpp"
|
#include "core/globals.hpp"
|
||||||
|
#include "base/CObject.hpp"
|
||||||
|
#include "entities/fwEntity.hpp"
|
||||||
|
#include "rage/netSyncDataNodeBase.hpp"
|
||||||
|
#include "rage/netSyncTree.hpp"
|
||||||
|
#include "gta/net_object_mgr.hpp"
|
||||||
|
#include "datanodes/door/CDoorCreationDataNode.hpp"
|
||||||
|
#include "datanodes/object/CObjectCreationDataNode.hpp"
|
||||||
|
#include "datanodes/ped/CPedAttachDataNode.hpp"
|
||||||
|
#include "datanodes/ped/CPedCreationDataNode.hpp"
|
||||||
|
#include "datanodes/pickup/CPickupCreationDataNode.hpp"
|
||||||
|
#include "datanodes/physical/CPhysicalAttachDataNode.hpp"
|
||||||
|
#include "datanodes/player/CPlayerAppearanceDataNode.hpp"
|
||||||
|
#include "datanodes/proximity_migrateable/CSectorDataNode.hpp"
|
||||||
|
#include "datanodes/train/CTrainGameStateDataNode.hpp"
|
||||||
|
#include "datanodes/vehicle/CVehicleCreationDataNode.hpp"
|
||||||
#include "network/netObject.hpp"
|
#include "network/netObject.hpp"
|
||||||
|
#include "natives.hpp"
|
||||||
#include "base/CBaseModelInfo.hpp"
|
#include "base/CBaseModelInfo.hpp"
|
||||||
#include "vehicle/CVehicleModelInfo.hpp"
|
#include "vehicle/CVehicleModelInfo.hpp"
|
||||||
#include "base/CObject.hpp"
|
|
||||||
#include "util/model_info.hpp"
|
#include "util/model_info.hpp"
|
||||||
|
|
||||||
namespace big
|
namespace big
|
||||||
@ -21,18 +36,298 @@ namespace big
|
|||||||
SuccessfullSync = 8
|
SuccessfullSync = 8
|
||||||
};
|
};
|
||||||
|
|
||||||
|
constexpr uint64_t operator ""_fnv1a(char const* str, std::size_t len)
|
||||||
|
{
|
||||||
|
auto const fnv_offset_basis = 14695981039346656037ULL;
|
||||||
|
auto const fnv_prime = 1099511628211ULL;
|
||||||
|
|
||||||
|
auto value = fnv_offset_basis;
|
||||||
|
for (auto i = 0; i < len; i++) {
|
||||||
|
value ^= static_cast<size_t>(str[i]);
|
||||||
|
value *= fnv_prime;
|
||||||
|
}
|
||||||
|
value ^= value >> 32;
|
||||||
|
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t crash_models[] = { RAGE_JOAAT("prop_dummy_01"), RAGE_JOAAT("prop_dummy_car"), RAGE_JOAAT("prop_dummy_light"), RAGE_JOAAT("prop_dummy_plane"), RAGE_JOAAT("slod_human"),
|
||||||
|
RAGE_JOAAT("slod_small_quadped"), RAGE_JOAAT("slod_large_quadped"), RAGE_JOAAT("prop_distantcar_night"), RAGE_JOAAT("prop_distantcar_day"), RAGE_JOAAT("hei_bh1_08_details4_em_night"),
|
||||||
|
RAGE_JOAAT("dt1_18_sq_night_slod"), RAGE_JOAAT("ss1_12_night_slod"), -1288391198, RAGE_JOAAT("h4_prop_bush_bgnvla_med_01"), RAGE_JOAAT("h4_prop_bush_bgnvla_lrg_01"),
|
||||||
|
RAGE_JOAAT("h4_prop_bush_buddleia_low_01"), RAGE_JOAAT("h4_prop_bush_ear_aa"), RAGE_JOAAT("h4_prop_bush_ear_ab"), RAGE_JOAAT("h4_prop_bush_fern_low_01"),
|
||||||
|
RAGE_JOAAT("h4_prop_bush_fern_tall_cc"), RAGE_JOAAT("h4_prop_bush_mang_ad"), RAGE_JOAAT("h4_prop_bush_mang_low_aa"), RAGE_JOAAT("h4_prop_bush_mang_low_ab"),
|
||||||
|
RAGE_JOAAT("h4_prop_bush_seagrape_low_01"), RAGE_JOAAT("prop_h4_ground_cover"), RAGE_JOAAT("h4_prop_weed_groundcover_01"), RAGE_JOAAT("h4_prop_grass_med_01"),
|
||||||
|
RAGE_JOAAT("h4_prop_grass_tropical_lush_01"), RAGE_JOAAT("h4_prop_grass_wiregrass_01"), RAGE_JOAAT("h4_prop_weed_01_plant"), RAGE_JOAAT("h4_prop_weed_01_row"),
|
||||||
|
RAGE_JOAAT("urbanweeds02_l1"), RAGE_JOAAT("proc_forest_grass01"), RAGE_JOAAT("prop_small_bushyba"), RAGE_JOAAT("arbitergt"), RAGE_JOAAT("astron2"), RAGE_JOAAT("cyclone2"),
|
||||||
|
RAGE_JOAAT("ignus2"), RAGE_JOAAT("s95"), RAGE_JOAAT("hc_gunman"), RAGE_JOAAT("v_res_d_dildo_a"), RAGE_JOAAT("v_res_d_dildo_b"), RAGE_JOAAT("v_res_d_dildo_c"),
|
||||||
|
RAGE_JOAAT("v_res_d_dildo_d"), RAGE_JOAAT("v_res_d_dildo_e"), RAGE_JOAAT("v_res_d_dildo_f"), RAGE_JOAAT("v_res_skateboard"), RAGE_JOAAT("prop_battery_01"), RAGE_JOAAT("prop_barbell_01"),
|
||||||
|
RAGE_JOAAT("prop_barbell_02"), RAGE_JOAAT("prop_bandsaw_01"), RAGE_JOAAT("prop_bbq_3"), RAGE_JOAAT("v_med_curtainsnewcloth2"), RAGE_JOAAT("bh1_07_flagpoles"),
|
||||||
|
92962485, RAGE_JOAAT("ig_wade") };
|
||||||
|
|
||||||
|
uint32_t cage_models[] = { RAGE_JOAAT("prop_rub_cage01a"), RAGE_JOAAT("prop_fnclink_05crnr1"), RAGE_JOAAT("prop_gold_cont_01"), RAGE_JOAAT("prop_feeder1"), RAGE_JOAAT("stt_prop_stunt_tube_s"),
|
||||||
|
RAGE_JOAAT("prop_feeder1_cr"), RAGE_JOAAT("p_cablecar_s") };
|
||||||
|
|
||||||
|
inline bool is_model_a_crash_model(uint32_t model) {
|
||||||
|
for (int i = 0; i < sizeof(crash_models) / sizeof(uint32_t); i++)
|
||||||
|
{
|
||||||
|
if (crash_models[i] == model) return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool is_model_a_cage_model(uint32_t model) {
|
||||||
|
for (int i = 0; i < sizeof(cage_models) / sizeof(uint32_t); i++)
|
||||||
|
{
|
||||||
|
if (cage_models[i] == model) return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define CLASS_TO_MANGLED_NAME(c) "?AV"#c"@@"
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
T* get_node_from_object(rage::netSyncNodeBase* node)
|
||||||
|
{
|
||||||
|
constexpr uint64_t hash = CLASS_TO_MANGLED_NAME(T)""_fnv1a;
|
||||||
|
if (node->IsParentNode())
|
||||||
|
{
|
||||||
|
for (auto child = node->m_first_child; child; child = child->m_next_sibling) {
|
||||||
|
T* attach_node = get_node_from_object<T>(child);
|
||||||
|
if(attach_node != nullptr)
|
||||||
|
return attach_node;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (node->IsDataNode())
|
||||||
|
{
|
||||||
|
if (typeid(*node).hash_code() == hash)
|
||||||
|
return dynamic_cast<T*>(node);
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool is_attachment_infinite(CPhysicalAttachDataNode* node, uint16_t object_id) {
|
||||||
|
if (rage::netObject* attached_object = (*g_pointers->m_network_object_mgr)->find_object_by_id(node->m_attached_to, false); attached_object)
|
||||||
|
{
|
||||||
|
if (rage::netSyncTree* tree = attached_object->GetSyncTree(); tree)
|
||||||
|
{
|
||||||
|
if (rage::netSyncNodeBase* base_node = tree->m_sync_node; base_node) {
|
||||||
|
|
||||||
|
const auto attached_attach_node = get_node_from_object<CPhysicalAttachDataNode>(base_node);
|
||||||
|
if (attached_attach_node && attached_attach_node->m_attached)
|
||||||
|
{
|
||||||
|
if (attached_attach_node->m_attached_to == object_id) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return is_attachment_infinite(attached_attach_node, object_id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool is_ped_attachment_infinite(CPedAttachDataNode* node, uint16_t object_id) {
|
||||||
|
if (rage::netObject* attached_object = (*g_pointers->m_network_object_mgr)->find_object_by_id(node->m_attached_to, false); attached_object)
|
||||||
|
{
|
||||||
|
if (rage::netSyncTree* tree = attached_object->GetSyncTree(); tree)
|
||||||
|
{
|
||||||
|
if (rage::netSyncNodeBase* base_node = tree->m_sync_node; base_node) {
|
||||||
|
|
||||||
|
const auto attached_attach_node = get_node_from_object<CPedAttachDataNode>(base_node);
|
||||||
|
if (attached_attach_node && attached_attach_node->m_attached)
|
||||||
|
{
|
||||||
|
if (attached_attach_node->m_attached_to == object_id) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return is_ped_attachment_infinite(attached_attach_node, object_id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool check_node(rage::netSyncNodeBase* node, CNetGamePlayer* sender, uint16_t object_id)
|
||||||
|
{
|
||||||
|
if (node->IsParentNode())
|
||||||
|
{
|
||||||
|
for (auto child = node->m_first_child; child; child = child->m_next_sibling) {
|
||||||
|
if (check_node(child, sender, object_id))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (node->IsDataNode())
|
||||||
|
{
|
||||||
|
//LOG(INFO) << typeid(*node).name() << ": " << HEX_TO_UPPER(typeid(*node).hash_code()); //Use this to get hashes for each node
|
||||||
|
switch (typeid(*node).hash_code()) {
|
||||||
|
case "?AVCDoorCreationDataNode@@"_fnv1a: //CDoorCreationDataNode
|
||||||
|
{
|
||||||
|
const auto creation_node = dynamic_cast<CDoorCreationDataNode*>(node);
|
||||||
|
if (is_model_a_crash_model(creation_node->m_model))
|
||||||
|
{
|
||||||
|
if (g->notifications.invalid_sync.log)
|
||||||
|
LOG(WARNING) << "Invalid door model: " << "Model: " << HEX_TO_UPPER(creation_node->m_model) << " From : " << sender->get_name();
|
||||||
|
if (g->notifications.invalid_sync.notify)
|
||||||
|
g_notification_service->push_warning(std::format("Invalid door model from {}", sender->get_name()), std::format("Model: 0x{:x}", creation_node->m_model));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case "?AVCPickupCreationDataNode@@"_fnv1a: //CPickupCreationDataNode
|
||||||
|
{
|
||||||
|
const auto creation_node = dynamic_cast<CPickupCreationDataNode*>(node);
|
||||||
|
if (is_model_a_crash_model(creation_node->m_custom_model))
|
||||||
|
{
|
||||||
|
if (g->notifications.invalid_sync.log)
|
||||||
|
LOG(WARNING) << "Invalid pickup model: " << "Model: " << HEX_TO_UPPER(creation_node->m_custom_model) << " From : " << sender->get_name();
|
||||||
|
if (g->notifications.invalid_sync.notify)
|
||||||
|
g_notification_service->push_warning(std::format("Invalid pickup model from {}", sender->get_name()), std::format("Model: 0x{:x}", creation_node->m_custom_model));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case "?AVCPhysicalAttachDataNode@@"_fnv1a: //CPhysicalAttachDataNode
|
||||||
|
{
|
||||||
|
const auto attach_node = dynamic_cast<CPhysicalAttachDataNode*>(node);
|
||||||
|
if (attach_node->m_attached && attach_node->m_attached_to == object_id)
|
||||||
|
{
|
||||||
|
if (g->notifications.invalid_sync.log)
|
||||||
|
LOG(WARNING) << "Infinite attachment: " << "Node: " << typeid(*node).name() << " From : " << sender->get_name();
|
||||||
|
if (g->notifications.invalid_sync.notify)
|
||||||
|
g_notification_service->push_warning(std::format("Infinite attachment from {}", sender->get_name()), std::format("Node: {}", typeid(*node).name()));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else if (attach_node->m_attached && is_attachment_infinite(attach_node, object_id))
|
||||||
|
{
|
||||||
|
if (g->notifications.invalid_sync.log)
|
||||||
|
LOG(WARNING) << "Infinite attachment v2: " << "Node: " << typeid(*node).name() << " From : " << sender->get_name();
|
||||||
|
if (g->notifications.invalid_sync.notify)
|
||||||
|
g_notification_service->push_warning(std::format("Infinite attachment v2 from {}", sender->get_name()), std::format("Node: {}", typeid(*node).name()));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case "?AVCPedCreationDataNode@@"_fnv1a: //CPedCreationDataNode
|
||||||
|
{
|
||||||
|
const auto creation_node = dynamic_cast<CPedCreationDataNode*>(node);
|
||||||
|
if (is_model_a_crash_model(creation_node->m_model))
|
||||||
|
{
|
||||||
|
if (g->notifications.invalid_sync.log)
|
||||||
|
LOG(WARNING) << "Invalid ped model: " << "Model: " << HEX_TO_UPPER(creation_node->m_model) << " From : " << sender->get_name();
|
||||||
|
if (g->notifications.invalid_sync.notify)
|
||||||
|
g_notification_service->push_warning(std::format("Invalid ped model from {}", sender->get_name()), std::format("Model: 0x{:x}", creation_node->m_model));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else if (creation_node->m_has_prop && is_model_a_crash_model(creation_node->m_prop_model)) {
|
||||||
|
if (g->notifications.invalid_sync.log)
|
||||||
|
LOG(WARNING) << "Invalid ped prop model: " << "Model: " << HEX_TO_UPPER(creation_node->m_prop_model) << " From : " << sender->get_name();
|
||||||
|
if (g->notifications.invalid_sync.notify)
|
||||||
|
g_notification_service->push_warning(std::format("Invalid ped prop model from {}", sender->get_name()), std::format("Model: 0x{:x}", creation_node->m_prop_model));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case "?AVCPedAttachDataNode@@"_fnv1a: //CPedAttachDataNode
|
||||||
|
{
|
||||||
|
const auto attach_node = dynamic_cast<CPedAttachDataNode*>(node);
|
||||||
|
if (attach_node->m_attached && attach_node->m_attached_to == object_id)
|
||||||
|
{
|
||||||
|
if (g->notifications.invalid_sync.log)
|
||||||
|
LOG(WARNING) << "Infinite ped attachment: " << "Node: " << typeid(*node).name() << " From : " << sender->get_name();
|
||||||
|
if (g->notifications.invalid_sync.notify)
|
||||||
|
g_notification_service->push_warning(std::format("Infinite ped attachment from {}", sender->get_name()), std::format("Node: {}", typeid(*node).name()));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else if (attach_node->m_attached && is_ped_attachment_infinite(attach_node, object_id))
|
||||||
|
{
|
||||||
|
if (g->notifications.invalid_sync.log)
|
||||||
|
LOG(WARNING) << "Infinite ped attachment v2: " << "Node: " << typeid(*node).name() << " From : " << sender->get_name();
|
||||||
|
if (g->notifications.invalid_sync.notify)
|
||||||
|
g_notification_service->push_warning(std::format("Infinite ped attachment v2 from {}", sender->get_name()), std::format("Node: {}", typeid(*node).name()));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case "?AVCVehicleCreationDataNode@@"_fnv1a: //CVehicleCreationDataNode
|
||||||
|
{
|
||||||
|
const auto vehicle_creation_node = dynamic_cast<CVehicleCreationDataNode*>(node);
|
||||||
|
if (is_model_a_crash_model(vehicle_creation_node->m_model)) {
|
||||||
|
if (g->notifications.invalid_sync.log)
|
||||||
|
LOG(WARNING) << "Invalid vehicle model: " << "Model: " << HEX_TO_UPPER(vehicle_creation_node->m_model) << " From : " << sender->get_name();
|
||||||
|
if (g->notifications.invalid_sync.notify)
|
||||||
|
g_notification_service->push_warning(std::format("Invalid vehicle model from {}", sender->get_name()), std::format("Model: 0x{:x}", vehicle_creation_node->m_model));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case "?AVCObjectCreationDataNode@@"_fnv1a: //CObjectCreationDataNode
|
||||||
|
{
|
||||||
|
const auto creation_node = dynamic_cast<CObjectCreationDataNode*>(node);
|
||||||
|
if (is_model_a_crash_model(creation_node->m_model)) {
|
||||||
|
if (g->notifications.invalid_sync.log)
|
||||||
|
LOG(WARNING) << "Invalid object model: " << "Model: " << HEX_TO_UPPER(creation_node->m_model) << " From : " << sender->get_name();
|
||||||
|
if (g->notifications.invalid_sync.notify)
|
||||||
|
g_notification_service->push_warning(std::format("Invalid object model from {}", sender->get_name()), std::format("Model: 0x{:x}", creation_node->m_model));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else if (is_model_a_cage_model(creation_node->m_model)) {
|
||||||
|
if (g->notifications.invalid_sync.log)
|
||||||
|
LOG(WARNING) << "Cage model: " << "Model: " << HEX_TO_UPPER(creation_node->m_model) << " From : " << sender->get_name();
|
||||||
|
if (g->notifications.invalid_sync.notify)
|
||||||
|
g_notification_service->push_warning(std::format("Cage model from {}", sender->get_name()), std::format("Model: 0x{:x}", creation_node->m_model));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case "?AVCPlayerAppearanceDataNode@@"_fnv1a: //CPlayerAppearanceDataNode
|
||||||
|
{
|
||||||
|
const auto player_appearance_node = dynamic_cast<CPlayerAppearanceDataNode*>(node);
|
||||||
|
if (is_model_a_crash_model(player_appearance_node->m_model_hash)) {
|
||||||
|
if (g->notifications.invalid_sync.log)
|
||||||
|
LOG(WARNING) << "Invalid player model: " << "Model: " << HEX_TO_UPPER(player_appearance_node->m_model_hash) << " From : " << sender->get_name();
|
||||||
|
if (g->notifications.invalid_sync.notify)
|
||||||
|
g_notification_service->push_warning(std::format("Invalid player model from {}", sender->get_name()), std::format("Model: 0x{:x}", player_appearance_node->m_model_hash));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case "?AVCSectorDataNode@@"_fnv1a: //CSectorDataNode
|
||||||
|
{
|
||||||
|
const auto sector_node = dynamic_cast<CSectorDataNode*>(node);
|
||||||
|
if (sector_node->m_pos_x == 712 || sector_node->m_pos_y == 712 || sector_node->m_pos_z == 712)
|
||||||
|
{
|
||||||
|
if (g->notifications.invalid_sync.log)
|
||||||
|
LOG(WARNING) << "Invalid sector position." << " From : " << sender->get_name();
|
||||||
|
if (g->notifications.invalid_sync.notify)
|
||||||
|
g_notification_service->push_warning(std::format("Invalid sector position from {}", sender->get_name()), "Invalid sector position.");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
int64_t hooks::received_clone_sync(CNetworkObjectMgr* mgr, CNetGamePlayer* src, CNetGamePlayer* dst, eObjType sync_type, uint16_t obj_id, rage::datBitBuffer* buffer, uint16_t unk, uint32_t timestamp) {
|
int64_t hooks::received_clone_sync(CNetworkObjectMgr* mgr, CNetGamePlayer* src, CNetGamePlayer* dst, eObjType sync_type, uint16_t obj_id, rage::datBitBuffer* buffer, uint16_t unk, uint32_t timestamp) {
|
||||||
if (auto sync_tree = g_pointers->m_get_sync_tree_for_type(mgr, sync_type); sync_tree && *g_pointers->m_is_session_started)
|
if (auto sync_tree = g_pointers->m_get_sync_tree_for_type(mgr, sync_type); sync_tree && *g_pointers->m_is_session_started)
|
||||||
{
|
{
|
||||||
if (auto net_obj = g_pointers->m_get_net_object(mgr, obj_id, true); net_obj)
|
if (auto net_obj = g_pointers->m_get_net_object(mgr, obj_id, true); net_obj)
|
||||||
{
|
{
|
||||||
auto tree_name = g_pointers->m_get_sync_type_info(sync_type, 0);
|
auto tree_name = g_pointers->m_get_sync_type_info(sync_type, 0);
|
||||||
bool invalidsync = false;
|
|
||||||
|
|
||||||
if (sync_type < eObjType::carObjType || sync_type > eObjType::unkObjType14)
|
if (sync_type < eObjType::carObjType || sync_type > eObjType::unkObjType14)
|
||||||
{
|
{
|
||||||
if (g->notifications.out_of_allowed_range_sync_type.log)
|
if (g->notifications.out_of_allowed_range_sync_type.log)
|
||||||
LOG(WARNING) << "Out of range sync: " << "Type: " << sync_type << " Tree name: " << tree_name << " From: " << src->get_name();
|
LOG(WARNING) << "Out of Bounds sync: " << "Type: " << sync_type << " Tree name: " << tree_name << " From: " << src->get_name();
|
||||||
if (g->notifications.out_of_allowed_range_sync_type.notify)
|
if (g->notifications.out_of_allowed_range_sync_type.notify)
|
||||||
g_notification_service->push_warning(std::format("Out Of Allowed Sync Range from {}", src->get_name()), std::format("Type {} in sync tree {}", std::uint16_t(sync_type), tree_name));
|
g_notification_service->push_warning(std::format("Out Of Allowed Sync Range from {}", src->get_name()), std::format("Type {} in sync tree {}", std::uint16_t(sync_type), tree_name));
|
||||||
}
|
}
|
||||||
@ -60,8 +355,25 @@ namespace big
|
|||||||
{
|
{
|
||||||
return SyncResponse::WrongOwner;
|
return SyncResponse::WrongOwner;
|
||||||
}
|
}
|
||||||
|
else if ((sync_type >= eObjType::bikeObjType && sync_type <= eObjType::heliObjType) || (sync_type >= eObjType::planeObjType && sync_type <= eObjType::submarineObjType) || (sync_type >= eObjType::trailerObjType && sync_type <= eObjType::trainObjType))
|
||||||
|
{
|
||||||
|
if(reinterpret_cast<CVehicleModelInfo*>(model_info)->m_vehicle_type != model_info::get_vehicle_model(model_info->m_hash)->m_vehicle_type)
|
||||||
|
return SyncResponse::WrongOwner;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint32_t pos = buffer->m_bitsRead;
|
||||||
|
g_pointers->m_read_bitbuffer_into_sync_tree(sync_tree, 2, 0, buffer, 0);
|
||||||
|
buffer->Seek(pos);
|
||||||
|
|
||||||
|
//LOG(INFO) << typeid(*tree).name() << ": " << HEX_TO_UPPER(typeid(*tree).hash_code()); //Use this to get hashes for each tree
|
||||||
|
|
||||||
|
if (sync_tree->m_child_node_count)
|
||||||
|
{
|
||||||
|
if (check_node(sync_tree->m_sync_node, src, obj_id))
|
||||||
|
return SyncResponse::CantApplyData;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (sync_type != eObjType::pedObjType) //We don't want to not sync a player, so we ensure it's not a ped
|
else if (sync_type != eObjType::pedObjType) //We don't want to not sync a player, so we ensure it's not a ped
|
||||||
{
|
{
|
||||||
|
@ -11,7 +11,7 @@ namespace big
|
|||||||
uint16_t event_id,
|
uint16_t event_id,
|
||||||
int event_index,
|
int event_index,
|
||||||
int event_handled_bitset,
|
int event_handled_bitset,
|
||||||
int unk,
|
int buffer_size,
|
||||||
rage::datBitBuffer* buffer
|
rage::datBitBuffer* buffer
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
@ -178,6 +178,6 @@ namespace big
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return g_hooking->get_original<received_event>()(event_manager, source_player, target_player, event_id, event_index, event_handled_bitset, unk, buffer);
|
return g_hooking->get_original<received_event>()(event_manager, source_player, target_player, event_id, event_index, event_handled_bitset, buffer_size, buffer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -330,6 +330,12 @@ namespace big
|
|||||||
m_get_sync_type_info = ptr.add(0x8C).rip().as<decltype(m_get_sync_type_info)>(); // 44 0F B7 C1 4C 8D 0D .as()
|
m_get_sync_type_info = ptr.add(0x8C).rip().as<decltype(m_get_sync_type_info)>(); // 44 0F B7 C1 4C 8D 0D .as()
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Read Bitbuffer Into Sync Tree
|
||||||
|
main_batch.add("RBIST", "E8 ? ? ? ? 48 8B BC 24 B0 00 00 00", [this](memory::handle ptr)
|
||||||
|
{
|
||||||
|
m_read_bitbuffer_into_sync_tree = ptr.add(1).rip().as<functions::read_bitbuffer_into_sync_tree>();
|
||||||
|
});
|
||||||
|
|
||||||
// Model Hash Table
|
// Model Hash Table
|
||||||
main_batch.add("MHT", "4C 03 05 ? ? ? ? EB 03", [this](memory::handle ptr)
|
main_batch.add("MHT", "4C 03 05 ? ? ? ? EB 03", [this](memory::handle ptr)
|
||||||
{
|
{
|
||||||
|
@ -100,6 +100,8 @@ namespace big
|
|||||||
functions::get_sync_tree_for_type m_get_sync_tree_for_type{};
|
functions::get_sync_tree_for_type m_get_sync_tree_for_type{};
|
||||||
functions::get_sync_type_info m_get_sync_type_info{};
|
functions::get_sync_type_info m_get_sync_type_info{};
|
||||||
functions::get_net_object m_get_net_object{};
|
functions::get_net_object m_get_net_object{};
|
||||||
|
functions::get_net_object_for_player m_get_net_object_for_player{};
|
||||||
|
functions::read_bitbuffer_into_sync_tree m_read_bitbuffer_into_sync_tree{};
|
||||||
//Sync Signatures END
|
//Sync Signatures END
|
||||||
|
|
||||||
PVOID m_send_net_info_to_lobby{};
|
PVOID m_send_net_info_to_lobby{};
|
||||||
|
Reference in New Issue
Block a user