From 06a215b90c1fbedb275241a4233d4fa9b3674222 Mon Sep 17 00:00:00 2001 From: Andreas Maerten <24669514+Yimura@users.noreply.github.com> Date: Sun, 2 Apr 2023 01:30:51 +0200 Subject: [PATCH] refactor(ContextMenu): improve code (#1173) * chore: remove unused classes from replay * feat(ContextMenu): keep drawing even if menu is open --- .../commands/player/toxic/kill_player.cpp | 84 +- src/backend/looped/player/toxic_options.cpp | 124 +- src/function_types.hpp | 278 ++-- src/gta/fwddec.hpp | 151 +- src/gta/replay.hpp | 232 ++- src/hooks/protections/received_event.cpp | 1362 ++++++++--------- .../context_menu/context_menu_service.cpp | 125 +- src/util/entity.hpp | 7 +- src/util/vehicle.hpp | 8 +- 9 files changed, 1158 insertions(+), 1213 deletions(-) diff --git a/src/backend/commands/player/toxic/kill_player.cpp b/src/backend/commands/player/toxic/kill_player.cpp index 1f34a1d9..bc0fffc8 100644 --- a/src/backend/commands/player/toxic/kill_player.cpp +++ b/src/backend/commands/player/toxic/kill_player.cpp @@ -1,43 +1,43 @@ -#include "backend/player_command.hpp" -#include "natives.hpp" -#include "pointers.hpp" - -namespace big -{ - class kill_player : player_command - { - using player_command::player_command; - - virtual CommandAccessLevel get_access_level() - { - return CommandAccessLevel::AGGRESSIVE; - } - - virtual void execute(player_ptr player, const std::vector& _args, const std::shared_ptr ctx) - { - if (!player->get_ped()) - return; - - g_pointers->m_send_network_damage((CEntity*)g_player_service->get_self()->get_ped(), - (CEntity*)player->get_ped(), - player->get_ped()->m_navigation->get_position(), - 0, - true, - RAGE_JOAAT("weapon_explosion"), - 10000.0f, - 2, - 0, - (1 << 4), - 0, - 0, - 0, - false, - false, - true, - true, - nullptr); - } - }; - - kill_player g_kill_player("kill", "Kill Player", "Kills the player, bypassing most forms of interior godmode", 0); +#include "backend/player_command.hpp" +#include "natives.hpp" +#include "pointers.hpp" + +namespace big +{ + class kill_player : player_command + { + using player_command::player_command; + + virtual CommandAccessLevel get_access_level() + { + return CommandAccessLevel::AGGRESSIVE; + } + + virtual void execute(player_ptr player, const std::vector& _args, const std::shared_ptr ctx) + { + if (!player->get_ped()) + return; + + g_pointers->m_send_network_damage(g_player_service->get_self()->get_ped(), + player->get_ped(), + player->get_ped()->m_navigation->get_position(), + 0, + true, + RAGE_JOAAT("weapon_explosion"), + 10000.0f, + 2, + 0, + (1 << 4), + 0, + 0, + 0, + false, + false, + true, + true, + nullptr); + } + }; + + kill_player g_kill_player("kill", "Kill Player", "Kills the player, bypassing most forms of interior godmode", 0); } \ No newline at end of file diff --git a/src/backend/looped/player/toxic_options.cpp b/src/backend/looped/player/toxic_options.cpp index 57b3846b..bdd49315 100644 --- a/src/backend/looped/player/toxic_options.cpp +++ b/src/backend/looped/player/toxic_options.cpp @@ -1,62 +1,62 @@ -#include "backend/looped/looped.hpp" -#include "gta/pickup_rewards.hpp" -#include "services/players/player_service.hpp" -#include "util/globals.hpp" -#include "util/misc.hpp" -#include "util/toxic.hpp" - -namespace big -{ - void looped::player_toxic_options() - { - if (!*g_pointers->m_is_session_started) - return; - - int rotate_cam_bits = 0; - - g_player_service->iterate([&rotate_cam_bits](const player_entry& entry) { - if (g_player_service->get_self()->get_ped() && entry.second->get_ped() && entry.second->get_ped()->m_health > 0) - { - if (entry.second->kill_loop && !(entry.second->get_ped()->m_damage_bits & (1 << 8))) - g_pointers->m_send_network_damage((CEntity*)g_player_service->get_self()->get_ped(), - (CEntity*)entry.second->get_ped(), - entry.second->get_ped()->m_navigation->get_position(), - 0, - true, - RAGE_JOAAT("weapon_explosion"), - 10000.0f, - 2, - 0, - (1 << 4), - 0, - 0, - 0, - false, - false, - true, - true, - nullptr); - - if (entry.second->explosion_loop) - toxic::blame_explode_player(entry.second, entry.second, EXP_TAG_SUBMARINE_BIG, 9999.0f, true, false, 9999.0f); - - if (entry.second->freeze_loop && entry.second->get_ped()->m_net_object) - g_pointers->m_clear_ped_tasks_network(entry.second->get_ped(), true); - - if (entry.second->ragdoll_loop && entry.second->get_ped()->m_net_object) - g_pointers->m_request_ragdoll(entry.second->get_ped()->m_net_object->m_object_id); - - if (entry.second->rotate_cam_loop) - rotate_cam_bits |= (1 << entry.second->id()); - } - - if (rotate_cam_bits) - { - const size_t arg_count = 3; - int64_t args[arg_count] = {(int64_t)eRemoteEvent::TSECommand, (int64_t)self::id, (int64_t)eRemoteEvent::TSECommandRotateCam}; - - g_pointers->m_trigger_script_event(1, args, arg_count, rotate_cam_bits); - } - }); - } -} +#include "backend/looped/looped.hpp" +#include "gta/pickup_rewards.hpp" +#include "services/players/player_service.hpp" +#include "util/globals.hpp" +#include "util/misc.hpp" +#include "util/toxic.hpp" + +namespace big +{ + void looped::player_toxic_options() + { + if (!*g_pointers->m_is_session_started) + return; + + int rotate_cam_bits = 0; + + g_player_service->iterate([&rotate_cam_bits](const player_entry& entry) { + if (g_player_service->get_self()->get_ped() && entry.second->get_ped() && entry.second->get_ped()->m_health > 0) + { + if (entry.second->kill_loop && !(entry.second->get_ped()->m_damage_bits & (1 << 8))) + g_pointers->m_send_network_damage(g_player_service->get_self()->get_ped(), + entry.second->get_ped(), + entry.second->get_ped()->m_navigation->get_position(), + 0, + true, + RAGE_JOAAT("weapon_explosion"), + 10000.0f, + 2, + 0, + (1 << 4), + 0, + 0, + 0, + false, + false, + true, + true, + nullptr); + + if (entry.second->explosion_loop) + toxic::blame_explode_player(entry.second, entry.second, EXP_TAG_SUBMARINE_BIG, 9999.0f, true, false, 9999.0f); + + if (entry.second->freeze_loop && entry.second->get_ped()->m_net_object) + g_pointers->m_clear_ped_tasks_network(entry.second->get_ped(), true); + + if (entry.second->ragdoll_loop && entry.second->get_ped()->m_net_object) + g_pointers->m_request_ragdoll(entry.second->get_ped()->m_net_object->m_object_id); + + if (entry.second->rotate_cam_loop) + rotate_cam_bits |= (1 << entry.second->id()); + } + + if (rotate_cam_bits) + { + const size_t arg_count = 3; + int64_t args[arg_count] = {(int64_t)eRemoteEvent::TSECommand, (int64_t)self::id, (int64_t)eRemoteEvent::TSECommandRotateCam}; + + g_pointers->m_trigger_script_event(1, args, arg_count, rotate_cam_bits); + } + }); + } +} diff --git a/src/function_types.hpp b/src/function_types.hpp index 6b82a6a5..7af1c914 100644 --- a/src/function_types.hpp +++ b/src/function_types.hpp @@ -1,139 +1,139 @@ -#pragma once -#include - -class CMsgJoinResponse; -class NetworkGameFilterMatchmakingComponent; -class sCloudFile; -class CPlayerGameStateDataNode; -class CVehicleGadgetDataNode; -enum eVehicleGadgetType : uint32_t; - -namespace rage -{ - class netConnectionManager; - class netConnectionPeer; - class snMsgRemoveGamersFromSessionCmd; - class snSession; - class snPlayer; - class CDynamicEntity; - class netTimeSyncMsg; - class snConnectToPeerTaskData; - class snConnectToPeerTaskResult; - class rlScHandle; - class rlQueryPresenceAttributesContext; - enum class eThreadState : uint32_t; -} - -namespace datafile_commands -{ - class SveFileObject; -} - -namespace big::functions -{ - using run_script_threads = bool (*)(std::uint32_t ops_to_execute); - using get_native_handler = rage::scrNativeHandler (*)(rage::scrNativeRegistrationTable* registration_table, rage::scrNativeHash hash); - using fix_vectors = void (*)(rage::scrNativeCallContext* call_ctx); - - using get_net_game_player = CNetGamePlayer* (*)(Player player); - - using trigger_script_event = void (*)(int event_group, int64_t* args, int arg_count, int player_bits); - - - using increment_stat_event = bool (*)(uint64_t net_event_struct, int64_t sender, int64_t a3); - - using ptr_to_handle = Entity (*)(void*); - using handle_to_ptr = rage::CDynamicEntity* (*)(Entity); - - using check_chat_profanity = int(__int64 chat_type, const char* input, const char** output); - using write_player_game_state_data_node = bool (*)(rage::netObject* plr, CPlayerGameStateDataNode* node); - - using get_gameplay_cam_coords = Vector3 (*)(); - - using get_screen_coords_for_world_coords = bool (*)(float* world_coords, float* out_x, float* out_y); - - using give_pickup_rewards = void (*)(int players, uint32_t hash); - - // Bitbuffer read/write START - using read_bitbuf_dword = bool (*)(rage::datBitBuffer* buffer, PVOID read, int bits); - using read_bitbuf_string = bool (*)(rage::datBitBuffer* buffer, char* read, int bits); - using read_bitbuf_bool = bool (*)(rage::datBitBuffer* buffer, bool* read, int bits); - using read_bitbuf_array = bool (*)(rage::datBitBuffer* buffer, PVOID read, int bits, int unk); - using write_bitbuf_qword = bool (*)(rage::datBitBuffer* buffer, uint64_t val, int bits); - using write_bitbuf_dword = bool (*)(rage::datBitBuffer* buffer, uint32_t val, int bits); - using write_bitbuf_int64 = bool (*)(rage::datBitBuffer* buffer, int64_t val, int bits); - using write_bitbuf_int32 = bool (*)(rage::datBitBuffer* buffer, int32_t val, int bits); - using write_bitbuf_bool = bool (*)(rage::datBitBuffer* buffer, bool val, int bits); - using write_bitbuf_array = bool (*)(rage::datBitBuffer* buffer, void* val, int bits, int unk); - - // Bitbuffer read/write END - // Received Event Signatures START - using send_event_ack = void (*)(rage::netEventMgr* event_manager, CNetGamePlayer* source_player, CNetGamePlayer* target_player, int event_index, int event_handled_bitset); - // Received Event Signatures END - - //Sync signatures START - using get_sync_type_info = const char* (*)(uint16_t sync_type, char a2); - - 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 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 - - using reset_network_complaints = void (*)(CNetComplaintMgr* mgr); - - using fidevice_get_device = rage::fiDevice* (*)(const char* path, bool allow_root); - using fipackfile_ctor = 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 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); - using start_matchmaking_find_sessions = bool (*)(int profile_index, int available_slots, NetworkGameFilterMatchmakingComponent* m_filter, unsigned int max_sessions, rage::rlSessionInfo* result_sessions, int* result_session_count, rage::rlTaskStatus* state); - using start_get_presence_attributes = bool (*)(int profile_index, rage::rlScHandle* handle, rage::rlQueryPresenceAttributesContext* contexts, int count, rage::rlTaskStatus* state); - using join_session_by_info = bool (*)(Network* network, rage::rlSessionInfo* info, int unk, int flags, rage::rlGamerHandle* handles, int handlecount); - - using generate_uuid = bool (*)(std::uint64_t* uuid); - - using get_vehicle_gadget_array_size = int (*)(eVehicleGadgetType type); - - using write_join_response_data = bool (*)(CMsgJoinResponse* response, void* data, int size, uint32_t* size_used); - - using queue_packet = bool (*)(rage::netConnectionManager* mgr, int msg_id, void* data, int size, int flags, void* unk); - - using generate_uuid = bool (*)(std::uint64_t* uuid); - - using send_chat_message = bool (*)(int64_t* send_chat_ptr, rage::rlGamerInfo* gamer_info, char* message, bool is_team); - - using send_network_damage = void (*)(CEntity* source, CEntity* target, rage::fvector3* position, int hit_component, bool override_default_damage, int weapon_type, float override_damage, int tire_index, int suspension_index, int flags, std::uint32_t action_result_hash, std::int16_t action_result_id, int action_unk, bool hit_weapon, bool hit_weapon_ammo_attachment, bool silenced, bool unk, rage::fvector3* impact_direction); - using request_ragdoll = void (*)(uint16_t object_id); - using request_control = void (*)(rage::netObject* net_object); - - using get_connection_peer = rage::netConnectionPeer* (*)(rage::netConnectionManager* manager, int peer_id); - using send_remove_gamer_cmd = void (*)(rage::netConnectionManager* net_connection_mgr, rage::netConnectionPeer* player, int connection_id, rage::snMsgRemoveGamersFromSessionCmd* cmd, int flags); - using handle_remove_gamer_cmd = void* (*)(rage::snSession* session, rage::snPlayer* origin, rage::snMsgRemoveGamersFromSessionCmd* cmd); - - using script_vm = rage::eThreadState (*)(uint64_t* stack, int64_t** scr_globals, rage::scrProgram* program, rage::scrThreadContext* ctx); - - using encode_session_info = bool (*)(rage::rlSessionInfo* info, char* buffer, int buffer_size, int* bytes_written); - using decode_session_info = bool (*)(rage::rlSessionInfo* out_info, char* buffer, int* bytes_read); - using decode_peer_info = bool (*)(rage::rlGamerInfoBase* info, char* buffer, int* bytes_read); - - using load_cloud_file = void (*)(sCloudFile** out_cloud_file, char* buffer, int size, const char* reason); - using set_as_active_cloud_file = void (*)(datafile_commands::SveFileObject* object, sCloudFile** file); - using save_json_data = char* (*)(datafile_commands::SveFileObject* object, int* out_length, const char* reason); - - using sync_network_time = bool (*)(rage::netConnectionManager* mgr, rage::netConnectionPeer* peer, int connection_id, rage::netTimeSyncMsg* msg, int flags); - using send_packet = bool (*)(rage::netConnectionManager* mgr, rage::netConnectionPeer* peer, int connection_id, void* data, int size, int flags); - using connect_to_peer = bool (*)(rage::netConnectionManager* mgr, rage::rlGamerInfoBase* gamer_info, rage::snConnectToPeerTaskData* data, rage::snConnectToPeerTaskResult* result, rage::rlTaskStatus* status); - - using clear_ped_tasks_network = void (*)(CPed* ped, bool immediately); - - using get_next_carriage = void* (*)(void* carriage); - using get_entity_attached_to = rage::CDynamicEntity* (*)(rage::CDynamicEntity* entity); - - using migrate_object = void (*)(CNetGamePlayer* player, rage::netObject* object, int type); -} +#pragma once +#include + +class CMsgJoinResponse; +class NetworkGameFilterMatchmakingComponent; +class sCloudFile; +class CPlayerGameStateDataNode; +class CVehicleGadgetDataNode; +enum eVehicleGadgetType : uint32_t; + +namespace rage +{ + class netConnectionManager; + class netConnectionPeer; + class snMsgRemoveGamersFromSessionCmd; + class snSession; + class snPlayer; + class CDynamicEntity; + class netTimeSyncMsg; + class snConnectToPeerTaskData; + class snConnectToPeerTaskResult; + class rlScHandle; + class rlQueryPresenceAttributesContext; + enum class eThreadState : uint32_t; +} + +namespace datafile_commands +{ + class SveFileObject; +} + +namespace big::functions +{ + using run_script_threads = bool (*)(std::uint32_t ops_to_execute); + using get_native_handler = rage::scrNativeHandler (*)(rage::scrNativeRegistrationTable* registration_table, rage::scrNativeHash hash); + using fix_vectors = void (*)(rage::scrNativeCallContext* call_ctx); + + using get_net_game_player = CNetGamePlayer* (*)(Player player); + + using trigger_script_event = void (*)(int event_group, int64_t* args, int arg_count, int player_bits); + + + using increment_stat_event = bool (*)(uint64_t net_event_struct, int64_t sender, int64_t a3); + + using ptr_to_handle = Entity (*)(void*); + using handle_to_ptr = rage::CDynamicEntity* (*)(Entity); + + using check_chat_profanity = int(__int64 chat_type, const char* input, const char** output); + using write_player_game_state_data_node = bool (*)(rage::netObject* plr, CPlayerGameStateDataNode* node); + + using get_gameplay_cam_coords = Vector3 (*)(); + + using get_screen_coords_for_world_coords = bool (*)(float* world_coords, float* out_x, float* out_y); + + using give_pickup_rewards = void (*)(int players, uint32_t hash); + + // Bitbuffer read/write START + using read_bitbuf_dword = bool (*)(rage::datBitBuffer* buffer, PVOID read, int bits); + using read_bitbuf_string = bool (*)(rage::datBitBuffer* buffer, char* read, int bits); + using read_bitbuf_bool = bool (*)(rage::datBitBuffer* buffer, bool* read, int bits); + using read_bitbuf_array = bool (*)(rage::datBitBuffer* buffer, PVOID read, int bits, int unk); + using write_bitbuf_qword = bool (*)(rage::datBitBuffer* buffer, uint64_t val, int bits); + using write_bitbuf_dword = bool (*)(rage::datBitBuffer* buffer, uint32_t val, int bits); + using write_bitbuf_int64 = bool (*)(rage::datBitBuffer* buffer, int64_t val, int bits); + using write_bitbuf_int32 = bool (*)(rage::datBitBuffer* buffer, int32_t val, int bits); + using write_bitbuf_bool = bool (*)(rage::datBitBuffer* buffer, bool val, int bits); + using write_bitbuf_array = bool (*)(rage::datBitBuffer* buffer, void* val, int bits, int unk); + + // Bitbuffer read/write END + // Received Event Signatures START + using send_event_ack = void (*)(rage::netEventMgr* event_manager, CNetGamePlayer* source_player, CNetGamePlayer* target_player, int event_index, int event_handled_bitset); + // Received Event Signatures END + + //Sync signatures START + using get_sync_type_info = const char* (*)(uint16_t sync_type, char a2); + + 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 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 + + using reset_network_complaints = void (*)(CNetComplaintMgr* mgr); + + using fidevice_get_device = rage::fiDevice* (*)(const char* path, bool allow_root); + using fipackfile_ctor = 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 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); + using start_matchmaking_find_sessions = bool (*)(int profile_index, int available_slots, NetworkGameFilterMatchmakingComponent* m_filter, unsigned int max_sessions, rage::rlSessionInfo* result_sessions, int* result_session_count, rage::rlTaskStatus* state); + using start_get_presence_attributes = bool (*)(int profile_index, rage::rlScHandle* handle, rage::rlQueryPresenceAttributesContext* contexts, int count, rage::rlTaskStatus* state); + using join_session_by_info = bool (*)(Network* network, rage::rlSessionInfo* info, int unk, int flags, rage::rlGamerHandle* handles, int handlecount); + + using generate_uuid = bool (*)(std::uint64_t* uuid); + + using get_vehicle_gadget_array_size = int (*)(eVehicleGadgetType type); + + using write_join_response_data = bool (*)(CMsgJoinResponse* response, void* data, int size, uint32_t* size_used); + + using queue_packet = bool (*)(rage::netConnectionManager* mgr, int msg_id, void* data, int size, int flags, void* unk); + + using generate_uuid = bool (*)(std::uint64_t* uuid); + + using send_chat_message = bool (*)(int64_t* send_chat_ptr, rage::rlGamerInfo* gamer_info, char* message, bool is_team); + + using send_network_damage = void (*)(rage::CEntity* source, rage::CEntity* target, rage::fvector3* position, int hit_component, bool override_default_damage, int weapon_type, float override_damage, int tire_index, int suspension_index, int flags, std::uint32_t action_result_hash, std::int16_t action_result_id, int action_unk, bool hit_weapon, bool hit_weapon_ammo_attachment, bool silenced, bool unk, rage::fvector3* impact_direction); + using request_ragdoll = void (*)(uint16_t object_id); + using request_control = void (*)(rage::netObject* net_object); + + using get_connection_peer = rage::netConnectionPeer* (*)(rage::netConnectionManager* manager, int peer_id); + using send_remove_gamer_cmd = void (*)(rage::netConnectionManager* net_connection_mgr, rage::netConnectionPeer* player, int connection_id, rage::snMsgRemoveGamersFromSessionCmd* cmd, int flags); + using handle_remove_gamer_cmd = void* (*)(rage::snSession* session, rage::snPlayer* origin, rage::snMsgRemoveGamersFromSessionCmd* cmd); + + using script_vm = rage::eThreadState (*)(uint64_t* stack, int64_t** scr_globals, rage::scrProgram* program, rage::scrThreadContext* ctx); + + using encode_session_info = bool (*)(rage::rlSessionInfo* info, char* buffer, int buffer_size, int* bytes_written); + using decode_session_info = bool (*)(rage::rlSessionInfo* out_info, char* buffer, int* bytes_read); + using decode_peer_info = bool (*)(rage::rlGamerInfoBase* info, char* buffer, int* bytes_read); + + using load_cloud_file = void (*)(sCloudFile** out_cloud_file, char* buffer, int size, const char* reason); + using set_as_active_cloud_file = void (*)(datafile_commands::SveFileObject* object, sCloudFile** file); + using save_json_data = char* (*)(datafile_commands::SveFileObject* object, int* out_length, const char* reason); + + using sync_network_time = bool (*)(rage::netConnectionManager* mgr, rage::netConnectionPeer* peer, int connection_id, rage::netTimeSyncMsg* msg, int flags); + using send_packet = bool (*)(rage::netConnectionManager* mgr, rage::netConnectionPeer* peer, int connection_id, void* data, int size, int flags); + using connect_to_peer = bool (*)(rage::netConnectionManager* mgr, rage::rlGamerInfoBase* gamer_info, rage::snConnectToPeerTaskData* data, rage::snConnectToPeerTaskResult* result, rage::rlTaskStatus* status); + + using clear_ped_tasks_network = void (*)(CPed* ped, bool immediately); + + using get_next_carriage = void* (*)(void* carriage); + using get_entity_attached_to = rage::CDynamicEntity* (*)(rage::CDynamicEntity* entity); + + using migrate_object = void (*)(CNetGamePlayer* player, rage::netObject* object, int type); +} diff --git a/src/gta/fwddec.hpp b/src/gta/fwddec.hpp index 3b0b31db..8a2d1260 100644 --- a/src/gta/fwddec.hpp +++ b/src/gta/fwddec.hpp @@ -1,75 +1,76 @@ -#pragma once - -namespace rage -{ - template - class atArray; - - class datBitBuffer; - class sysMemAllocator; - - class scriptIdBase; - class scriptId; - class scriptHandler; - class scriptHandlerNetComponent; - class scriptHandlerObject; - class scriptHandlerMgr; - - class scrProgram; - class scrProgramTable; - - class scrThreadContext; - class scrThread; - class tlsContext; - - class netLoggingInterface; - class netLogStub; - - class netPlayer; - class netPlayerMgr; - - class netGameEvent; - class netEventMgr; - - class netSyncTree; - - class netObject; - class netObjectMgrBase; - - class scrNativeCallContext; - class scrNativeRegistration; - class scrNativeRegistrationTable; - - class fwRefAwareBase; - class fwExtensibleBase; - class fwArchetype; - - class fiDevice; - class fiPackfile; - - class rlSessionInfo; - class rlSessionByGamerTaskResult; -} - -class GtaThread; - -class CGameScriptId; -class CGameScriptHandler; -class CGameScriptHandlerNetwork; -class CGameScriptHandlerMgr; - -class CEntity; -class CPhysical; - -class CObject; -class CPickup; - -class CPedFactory; -class CVehicleFactory; - -class Network; -class CNetGamePlayer; -class CNetworkPlayerMgr; -class CPlayerInfo; -class CNetworkObjectMgr; -class CNetComplaintMgr; +#pragma once + +namespace rage +{ + template + class atArray; + + class CEntity; + + class datBitBuffer; + class sysMemAllocator; + + class scriptIdBase; + class scriptId; + class scriptHandler; + class scriptHandlerNetComponent; + class scriptHandlerObject; + class scriptHandlerMgr; + + class scrProgram; + class scrProgramTable; + + class scrThreadContext; + class scrThread; + class tlsContext; + + class netLoggingInterface; + class netLogStub; + + class netPlayer; + class netPlayerMgr; + + class netGameEvent; + class netEventMgr; + + class netSyncTree; + + class netObject; + class netObjectMgrBase; + + class scrNativeCallContext; + class scrNativeRegistration; + class scrNativeRegistrationTable; + + class fwRefAwareBase; + class fwExtensibleBase; + class fwArchetype; + + class fiDevice; + class fiPackfile; + + class rlSessionInfo; + class rlSessionByGamerTaskResult; +} + +class GtaThread; + +class CGameScriptId; +class CGameScriptHandler; +class CGameScriptHandlerNetwork; +class CGameScriptHandlerMgr; + +class CPhysical; + +class CObject; +class CPickup; + +class CPedFactory; +class CVehicleFactory; + +class Network; +class CNetGamePlayer; +class CNetworkPlayerMgr; +class CPlayerInfo; +class CNetworkObjectMgr; +class CNetComplaintMgr; diff --git a/src/gta/replay.hpp b/src/gta/replay.hpp index d005be5b..d9ef100c 100644 --- a/src/gta/replay.hpp +++ b/src/gta/replay.hpp @@ -1,140 +1,94 @@ -#pragma once -#pragma pack(push, 4) - -#include "common.hpp" -#include "fwddec.hpp" - -namespace rage -{ - class CObject : public fwEntity - { - public: - };//Size: 0x018C - - class CPedFactory - { - public: - virtual ~CPedFactory() = default; - class CPed* m_local_ped;//0x0008 - }; //Size: 0x0010 - - //CUSTOM CLASS TO IMPROVE R* SHIT CLASS STRUCTURE - class CEntityHandle - { - public: - class fwEntity* m_entity_ptr;//0x0000 - int32_t m_handle; //0x0008 - char pad_000C[4]; //0x000C - }; //Size: 0x0010 - static_assert(sizeof(CEntityHandle) == 0x10, "CEntityHandle is not properly sized"); - - class CObjectHandle - { - public: - class CObject* m_object;//0x0000 - int32_t m_handle; //0x0008 - char pad_000C[4]; //0x000C - }; //Size: 0x0010 - static_assert(sizeof(CObjectHandle) == 0x10, "CObjectHandle is not properly sized"); - - class CObjectList - { - public: - class CEntityHandle m_objects[2300];//0x0000 - }; //Size: 0x8FC0 - - class CObjectInterface - { - public: - char pad_0000[344]; //0x0000 - class CObjectList* m_object_list;//0x0158 - int32_t m_max_objects; //0x0160 - char pad_0164[4]; //0x0164 - int32_t m_cur_objects; //0x0168 - - rage::fwEntity* get_object(const int& index) - { - if (index < m_max_objects) - return m_object_list->m_objects[index].m_entity_ptr; - return nullptr; - } - };//Size: 0x016C - - class CPedHandle - { - public: - class CPed* m_ped;//0x0000 - int32_t m_handle; //0x0008 - char pad_000C[4]; //0x000C - }; //Size: 0x0010 - static_assert(sizeof(CPedHandle) == 0x10, "CPedHandle is not properly sized"); - - class CPedList - { - public: - //CHANGED FROM CPedHandle - class CEntityHandle m_peds[256];//0x0000 - }; //Size: 0x1000 - - class CPedInterface - { - public: - char pad_0000[256]; //0x0000 - class CPedList* m_ped_list;//0x0100 - int32_t m_max_peds; //0x0108 - char pad_010C[4]; //0x010C - int32_t m_cur_peds; //0x0110 - - fwEntity* get_ped(const int& index) - { - if (index < m_max_peds) - return m_ped_list->m_peds[index].m_entity_ptr; - return nullptr; - } - };//Size: 0x0114 - - class CVehicleHandle - { - public: - class CAutomobile* m_vehicle;//0x0000 - int32_t m_handle; //0x0008 - char pad_000C[4]; //0x000C - }; //Size: 0x0010 - static_assert(sizeof(CVehicleHandle) == 0x10, "CVehicleHandle is not properly sized"); - - class CVehicleList - { - public: - //CHANGED FROM CVehicleHandle - class CEntityHandle m_vehicles[300];//0x0000 - }; //Size: 0x12C0 - - class CVehicleInterface - { - public: - char pad_0000[384]; //0x0000 - class CVehicleList* m_vehicle_list;//0x0180 - int32_t m_max_vehicles; //0x0188 - char pad_018C[4]; //0x018C - int32_t m_cur_vehicles; //0x0190 - - fwEntity* get_vehicle(const int& index) - { - if (index < m_max_vehicles) - return m_vehicle_list->m_vehicles[index].m_entity_ptr; - return nullptr; - } - };//Size: 0x0194 - - - class CReplayInterface - { - public: - char pad_0000[16]; //0x0000 - class CVehicleInterface* m_vehicle_interface;//0x0010 - class CPedInterface* m_ped_interface; //0x0018 - char pad_0020[8]; //0x0020 - class CObjectInterface* m_object_interface; //0x0028 - }; //Size: 0x0030 -} +#pragma once +#pragma pack(push, 4) + +#include "common.hpp" +#include "fwddec.hpp" +#include "base/CObject.hpp" + +namespace rage +{ + template + class CEntityEntry + { + public: + T* m_entity_ptr; //0x0000 + int32_t m_handle; //0x0008 + char pad_000C[4]; //0x000C + }; //Size: 0x0010 + static_assert(sizeof(CEntityEntry) == 0x10, "CEntityHandle is not properly sized"); + + class CObjectEntry : public CEntityEntry + { + }; + + class CPedEntry : public CEntityEntry + { + }; + + class CVehicleEntry : public CEntityEntry + { + }; //Size: 0x8FC0 + + class CObjectInterface + { + public: + char pad_0000[344]; //0x0000 + std::array* m_object_list; //0x0158 + int32_t m_max_objects; //0x0160 + char pad_0164[4]; //0x0164 + int32_t m_cur_objects; //0x0168 + + CObject* get_object(const int& index) + { + if (index < m_max_objects) + return (*m_object_list)[index].m_entity_ptr; + return nullptr; + } + }; //Size: 0x016C + + class CPedInterface + { + public: + char pad_0000[256]; //0x0000 + std::array* m_ped_list; //0x0100 + int32_t m_max_peds; //0x0108 + char pad_010C[4]; //0x010C + int32_t m_cur_peds; //0x0110 + + CPed* get_ped(const int& index) + { + if (index < m_max_peds) + return (*m_ped_list)[index].m_entity_ptr; + return nullptr; + } + }; //Size: 0x0114 + + class CVehicleInterface + { + public: + char pad_0000[384]; //0x0000 + std::array* m_vehicle_list; //0x0180 + int32_t m_max_vehicles; //0x0188 + char pad_018C[4]; //0x018C + int32_t m_cur_vehicles; //0x0190 + + CVehicle* get_vehicle(const int& index) + { + if (index < m_max_vehicles) + return (*m_vehicle_list)[index].m_entity_ptr; + return nullptr; + } + }; //Size: 0x0194 + + + class CReplayInterface + { + public: + char pad_0000[16]; //0x0000 + class CVehicleInterface* m_vehicle_interface; //0x0010 + class CPedInterface* m_ped_interface; //0x0018 + char pad_0020[8]; //0x0020 + class CObjectInterface* m_object_interface; //0x0028 + }; //Size: 0x0030 +} #pragma pack(pop) \ No newline at end of file diff --git a/src/hooks/protections/received_event.cpp b/src/hooks/protections/received_event.cpp index c2ee2cf0..04d07bc1 100644 --- a/src/hooks/protections/received_event.cpp +++ b/src/hooks/protections/received_event.cpp @@ -1,681 +1,681 @@ -#include "fiber_pool.hpp" -#include "gta/enums.hpp" -#include "gta/net_game_event.hpp" -#include "gta/script_id.hpp" -#include "hooking.hpp" -#include "util/math.hpp" -#include "util/notify.hpp" -#include "util/toxic.hpp" - -#include -#include - -namespace big -{ - static void script_id_deserialize(CGameScriptId& id, rage::datBitBuffer& buffer) - { - id.m_hash = buffer.Read(32); - id.m_timestamp = buffer.Read(32); - - if (buffer.Read(1)) - id.m_position_hash = buffer.Read(32); - - if (buffer.Read(1)) - id.m_instance_id = buffer.Read(8); - } - - void scan_weapon_damage_event(CNetGamePlayer* player, rage::datBitBuffer* buffer) - { - uint8_t damageType; - uint32_t weaponType;// weaponHash - - bool overrideDefaultDamage; - bool hitEntityWeapon; - bool hitWeaponAmmoAttachment; - bool silenced; - - uint32_t damageFlags; - bool hasActionResult; - - uint32_t actionResultName; - uint16_t actionResultId; - uint32_t f104; - - uint32_t weaponDamage; - bool isNetTargetPos; - - rage::fvector3 localPos; - - bool f112; - - uint32_t damageTime; - bool willKill; - uint32_t f120; - bool hasVehicleData; - - uint16_t f112_1; - - uint16_t parentGlobalId;// Source entity? - uint16_t hitGlobalId; // Target entity? - - uint8_t tyreIndex; - uint8_t suspensionIndex; - uint8_t hitComponent; - - bool f133; - bool hasImpactDir; - - rage::fvector3 impactDir; - - damageType = buffer->Read(2); - weaponType = buffer->Read(32); - - overrideDefaultDamage = buffer->Read(1); - hitEntityWeapon = buffer->Read(1); - hitWeaponAmmoAttachment = buffer->Read(1); - silenced = buffer->Read(1); - - damageFlags = buffer->Read(24); - // (damageFlags >> 1) & 1 - hasActionResult = buffer->Read(1); - - if (hasActionResult) - { - actionResultName = buffer->Read(32); - actionResultId = buffer->Read(16); - f104 - = buffer->Read(32); - } - - if (overrideDefaultDamage) - { - weaponDamage = buffer->Read(17); - } - else - { - weaponDamage = 0; - } - - bool _f92 = buffer->Read(1); - - if (_f92) - { - buffer->Read(4); - } - - isNetTargetPos = buffer->Read(1); - - if (isNetTargetPos) - { - localPos.x = buffer->ReadSignedFloat(16, 55.f);// divisor: 0x425C0000 - localPos.y = buffer->ReadSignedFloat(16, 55.f); - localPos.z = buffer->ReadSignedFloat(16, 55.f); - } - - if (damageType == 3) - { - damageTime = buffer->Read(32); - willKill = buffer->Read(1); - - if (hasActionResult) - { - hitGlobalId = buffer->Read(13); - } - else - { - hitGlobalId = 0; - } - - f112 = buffer->Read(1); - - if (!f112) - { - f112_1 = buffer->Read(11); - } - else - { - f112_1 = buffer->Read(16); - } - } - else - { - parentGlobalId = buffer->Read(13);// +118 - hitGlobalId = buffer->Read(13);// +120 - } - - if (damageType < 2) - { - localPos.x = buffer->ReadSignedFloat(16, 55.f);// divisor: 0x425C0000 - localPos.y = buffer->ReadSignedFloat(16, 55.f); - localPos.z = buffer->ReadSignedFloat(16, 55.f); - - if (damageType == 1) - { - hasVehicleData = buffer->Read(1); - - if (hasVehicleData) - { - tyreIndex = buffer->Read(4);// +122 - suspensionIndex = buffer->Read(4);// +123 - } - } - } - else - { - hitComponent = buffer->Read(5);// +108 - } - - f133 = buffer->Read(1); - hasImpactDir = buffer->Read(1); - - if (hasImpactDir) - { - impactDir.x = buffer->ReadSignedFloat(16, 6.2831854820251f);// divisor: 0x40C90FDB - impactDir.y = buffer->ReadSignedFloat(16, 6.2831854820251f); - impactDir.z = buffer->ReadSignedFloat(16, 6.2831854820251f); - } - - buffer->Seek(0); - - // LOG(INFO) << localPos.x << " " << localPos.y << " " << localPos.z << ". " << math::distance_between_vectors(localPos, *g_local_player->m_navigation->get_position()) << " " << (g_local_player->m_net_object->m_object_id == hitGlobalId ? "TRUE" : "FALSE") << " " << damageType << " " << damageFlags; - - if (damageType == 3 && (damageFlags & (1 << 1)) == 0) - hitGlobalId = g_local_player ? g_local_player->m_net_object->m_object_id : 0; - - if (g.session.damage_karma && g_local_player && g_local_player->m_net_object - && (g_local_player->m_net_object->m_object_id == hitGlobalId - || math::distance_between_vectors(localPos, *g_local_player->m_navigation->get_position()) < 1.5f)) - { - int id = player->m_player_id; - g_fiber_pool->queue_job([id, hitComponent, overrideDefaultDamage, weaponType, weaponDamage, tyreIndex, suspensionIndex, damageFlags, actionResultName, actionResultId, f104, hitEntityWeapon, hitWeaponAmmoAttachment, silenced, hasImpactDir, impactDir, localPos] { - auto player = g_player_service->get_by_id(id); - - if (!player->is_valid() || !player->get_ped()) - return; - - g_pointers->m_send_network_damage((CEntity*)g_player_service->get_self()->get_ped(), - (CEntity*)player->get_ped(), - (rage::fvector3*)&localPos, - hitComponent, - overrideDefaultDamage, - weaponType, - weaponDamage, - tyreIndex, - suspensionIndex, - damageFlags, - actionResultName, - actionResultId, - f104, - hitEntityWeapon, - hitWeaponAmmoAttachment, - silenced, - false, - player->get_ped()->m_navigation->get_position()); - }); - } - } - - void scan_explosion_event(CNetGamePlayer* player, rage::datBitBuffer* buffer) - { - uint16_t f186; - uint16_t f208; - int ownerNetId; - uint16_t f214; - eExplosionTag explosionType; - float damageScale; - - float posX; - float posY; - float posZ; - - bool f242; - uint16_t f104; - float cameraShake; - - bool isAudible; - bool f189; - bool isInvisible; - bool f126; - bool f241; - bool f243; - - uint16_t f210; - - float unkX; - float unkY; - float unkZ; - - bool f190; - bool f191; - - uint32_t f164; - - float posX224; - float posY224; - float posZ224; - - bool f240; - uint16_t f218; - bool f216; - - // clang-format off - - f186 = buffer->Read(16); - f208 = buffer->Read(13); - ownerNetId = buffer->Read(13); - f214 = buffer->Read(13); // 1604+ - explosionType = (eExplosionTag)buffer->ReadSigned(8);// 1604+ bit size - damageScale = buffer->Read(8) / 255.0f; - - posX = buffer->ReadSignedFloat(22, 27648.0f); - posY = buffer->ReadSignedFloat(22, 27648.0f); - posZ = buffer->ReadFloat(22, 4416.0f) - 1700.0f; - - f242 = buffer->Read(1); - f104 = buffer->Read(16); - cameraShake = buffer->Read(8) / 127.0f; - - isAudible = buffer->Read(1); - f189 = buffer->Read(1); - isInvisible = buffer->Read(1); - f126 = buffer->Read(1); - f241 = buffer->Read(1); - f243 = buffer->Read(1);// 1604+ - - f210 = buffer->Read(13); - - unkX = buffer->ReadSignedFloat(16, 1.1f); - unkY = buffer->ReadSignedFloat(16, 1.1f); - unkZ = buffer->ReadSignedFloat(16, 1.1f); - - f190 = buffer->Read(1); - f191 = buffer->Read(1); - f164 = buffer->Read(32); - - if (f242) - { - posX224 = buffer->ReadSignedFloat(31, 27648.0f); - posY224 = buffer->ReadSignedFloat(31, 27648.0f); - posZ224 = buffer->ReadFloat(31, 4416.0f) - 1700.0f; - } - else - { - posX224 = 0; - posY224 = 0; - posZ224 = 0; - } - - auto f168 = buffer->Read(32);// >= 1868: f_168 - - - f240 = buffer->Read(1); - if (f240) - { - f218 = buffer->Read(16); - - if (f191) - { - f216 = buffer->Read(8); - } - } - - buffer->Seek(0); - - auto object = g_pointers->m_get_net_object(*g_pointers->m_network_object_mgr, ownerNetId, true); - auto entity = object ? object->GetGameObject() : nullptr; - - auto offset_object = g_pointers->m_get_net_object(*g_pointers->m_network_object_mgr, f210, true); - - if (f208 == 0 && entity && entity->m_entity_type == 4 && reinterpret_cast(entity)->m_player_info - && player->m_player_info->m_ped && player->m_player_info->m_ped->m_net_object - && ownerNetId != player->m_player_info->m_ped->m_net_object->m_object_id && !offset_object) - { - g_notification_service->push_error("WARNING"_T.data(), - std::vformat("BLAMED_FOR_EXPLOSION"_T, - std::make_format_args(player->get_name(), - reinterpret_cast(entity)->m_player_info->m_net_player_data.m_name))); - session::add_infraction(g_player_service->get_by_id(player->m_player_id), Infraction::BLAME_EXPLOSION_DETECTED); - return; - } - - if (g.session.explosion_karma && g_local_player - && math::distance_between_vectors({posX, posY, posZ}, *g_local_player->m_navigation->get_position()) < 3.0f) - { - int id = player->m_player_id; - g_fiber_pool->queue_job([id, explosionType, damageScale, cameraShake, isAudible, isInvisible] { - toxic::blame_explode_player(g_player_service->get_self(), g_player_service->get_by_id(id), explosionType, damageScale, isAudible, isInvisible, cameraShake); - }); - } - - // clang-format on - } - - void hooks::received_event(rage::netEventMgr* event_manager, CNetGamePlayer* source_player, CNetGamePlayer* target_player, uint16_t event_id, int event_index, int event_handled_bitset, int buffer_size, rage::datBitBuffer* buffer) - { - if (event_id > 91u) - { - g_pointers->m_send_event_ack(event_manager, source_player, target_player, event_index, event_handled_bitset); - return; - } - - const auto event_name = *(char**)((DWORD64)event_manager + 8i64 * event_id + 243376); - if (event_name == nullptr || source_player == nullptr || source_player->m_player_id < 0 || source_player->m_player_id >= 32) - { - g_pointers->m_send_event_ack(event_manager, source_player, target_player, event_index, event_handled_bitset); - return; - } - - auto plyr = g_player_service->get_by_id(source_player->m_player_id); - - switch (static_cast(event_id)) - { - case eNetworkEvents::KICK_VOTES_EVENT: - { - std::uint32_t player_bitfield = buffer->Read(32); - if (player_bitfield & (1 << target_player->m_player_id)) - { - g.reactions.kick_vote.process(plyr); - } - buffer->Seek(0); - break; - } - case eNetworkEvents::NETWORK_INCREMENT_STAT_EVENT: - { - const auto increment_stat_event = std::make_unique(); - buffer->ReadDword(&increment_stat_event->m_stat, 0x20); - buffer->ReadDword(&increment_stat_event->m_amount, 0x20); - if (hooks::increment_stat_event(increment_stat_event.get(), source_player)) - { - g_pointers->m_send_event_ack(event_manager, source_player, target_player, event_index, event_handled_bitset); - return; - } - buffer->Seek(0); - break; - } - case eNetworkEvents::SCRIPT_ENTITY_STATE_CHANGE_EVENT: - { - uint16_t entity = buffer->Read(13); - auto type = buffer->Read(4); - uint32_t unk = buffer->Read(32); - if (type == ScriptEntityChangeType::SettingOfTaskVehicleTempAction) - { - uint16_t ped_id = buffer->Read(13); - uint32_t action = buffer->Read(8); - - if ((action >= 15 && action <= 18) || action == 33) - { - g_pointers->m_send_event_ack(event_manager, source_player, target_player, event_index, event_handled_bitset); - notify::crash_blocked(source_player, "vehicle temp action"); - return; - } - } - else if (type > ScriptEntityChangeType::SetVehicleExclusiveDriver || type < ScriptEntityChangeType::BlockingOfNonTemporaryEvents) - { - notify::crash_blocked(source_player, "invalid script entity change type"); - g_pointers->m_send_event_ack(event_manager, source_player, target_player, event_index, event_handled_bitset); - return; - } - buffer->Seek(0); - break; - } - case eNetworkEvents::SCRIPTED_GAME_EVENT: - { - const auto scripted_game_event = std::make_unique(); - buffer->ReadDword(&scripted_game_event->m_args_size, 32); - if (scripted_game_event->m_args_size - 1 <= 0x1AF) - buffer->ReadArray(&scripted_game_event->m_args, 8 * scripted_game_event->m_args_size); - - if (hooks::scripted_game_event(scripted_game_event.get(), source_player)) - { - g_pointers->m_send_event_ack(event_manager, source_player, target_player, event_index, event_handled_bitset); - - return; - } - buffer->Seek(0); - - break; - } - case eNetworkEvents::NETWORK_CLEAR_PED_TASKS_EVENT: - { - int net_id = buffer->Read(13); - - if (g_local_player && g_local_player->m_net_object && g_local_player->m_net_object->m_object_id == net_id) - { - g_pointers->m_send_event_ack(event_manager, source_player, target_player, event_index, event_handled_bitset); - g.reactions.clear_ped_tasks.process(plyr); - return; - } - - buffer->Seek(0); - break; - } - case eNetworkEvents::RAGDOLL_REQUEST_EVENT: - { - int net_id = buffer->Read(13); - - if (g_local_player && g_local_player->m_net_object && g_local_player->m_net_object->m_object_id == net_id) - { - g_pointers->m_send_event_ack(event_manager, source_player, target_player, event_index, event_handled_bitset); - g.reactions.remote_ragdoll.process(plyr); - return; - } - - buffer->Seek(0); - break; - } - // Don't block this event, we still want to report this player - // because if we still report others, our account seems less fishy - case eNetworkEvents::REPORT_CASH_SPAWN_EVENT: - { - uint32_t money; - - buffer->Seek(64); - buffer->ReadDword(&money, 32); - buffer->Seek(0); - - if (money >= 2000) - { - g.reactions.report_cash_spawn.process(plyr); - } - - break; - } - // player sending this event is a modder - case eNetworkEvents::REPORT_MYSELF_EVENT: - { - if (auto plyr = g_player_service->get_by_id(source_player->m_player_id)) - session::add_infraction(plyr, Infraction::TRIGGERED_ANTICHEAT); - - g.reactions.modder_detection.process(plyr); - break; - } - case eNetworkEvents::REQUEST_CONTROL_EVENT: - { - int net_id = buffer->Read(13); - if (g_local_player && g_local_player->m_vehicle && g_local_player->m_vehicle->m_net_object - && g_local_player->m_vehicle->m_net_object->m_object_id == net_id && g_local_player->m_vehicle->m_driver == g_local_player) - { - g_pointers->m_send_event_ack(event_manager, source_player, target_player, event_index, event_handled_bitset); - g.reactions.request_control_event.process(plyr); - return; - } - buffer->Seek(0); - break; - } - case eNetworkEvents::SCRIPT_WORLD_STATE_EVENT: - { - auto type = buffer->Read(4); - buffer->Read(1); - CGameScriptId id; - script_id_deserialize(id, *buffer); - - if (type == WorldStateDataType::Rope) - { - buffer->Read(9); // network rope id - buffer->Read(19);// pos x - buffer->Read(19);// pos y - buffer->Read(19);// pos z - buffer->Read(19);// rot x - buffer->Read(19);// rot y - buffer->Read(19);// rot z - buffer->Read(16);// length - int type = buffer->Read(4); - float initial_length = buffer->Read(16); - float min_length = buffer->Read(16); - - if (type == 0 || initial_length < min_length)// https://docs.fivem.net/natives/?_0xE832D760399EB220 - { - // most definitely a crash - LOG(INFO) << std::hex << std::uppercase << "0x" << id.m_hash; - notify::crash_blocked(source_player, "rope"); - g_pointers->m_send_event_ack(event_manager, source_player, target_player, event_index, event_handled_bitset); - return; - } - } - else if (type == WorldStateDataType::PopGroupOverride) - { - int pop_schedule = buffer->ReadSigned(8);// Pop Schedule - int pop_group = buffer->Read(32); // Pop Group - int percentage = buffer->Read(7); // Percentage - - if (pop_group == 0 && (percentage == 0 || percentage == 103)) - { - notify::crash_blocked(source_player, "pop group override"); - g_pointers->m_send_event_ack(event_manager, source_player, target_player, event_index, event_handled_bitset); - return; - } - } - else if (type > WorldStateDataType::VehiclePlayerLocking || type < WorldStateDataType::CarGen) - { - notify::crash_blocked(source_player, "invalid world state type"); - g_pointers->m_send_event_ack(event_manager, source_player, target_player, event_index, event_handled_bitset); - return; - } - - buffer->Seek(0); - break; - } - case eNetworkEvents::REMOVE_WEAPON_EVENT: - { - int net_id = buffer->Read(13); - uint32_t hash = buffer->Read(32); - - if (hash == RAGE_JOAAT("WEAPON_UNARMED")) - { - notify::crash_blocked(source_player, "remove unarmed"); - g_pointers->m_send_event_ack(event_manager, source_player, target_player, event_index, event_handled_bitset); - return; - } - - if (g_local_player && g_local_player->m_net_object && g_local_player->m_net_object->m_object_id == net_id) - { - g_notification_service->push_warning("PROTECTIONS"_T.data(), - std::vformat("REMOVE_WEAPON_ATTEMPT"_T, std::make_format_args(source_player->get_name()))); - g_pointers->m_send_event_ack(event_manager, source_player, target_player, event_index, event_handled_bitset); - return; - } - - buffer->Seek(0); - break; - } - case eNetworkEvents::REMOVE_ALL_WEAPONS_EVENT: - { - int net_id = buffer->Read(13); - - if (g_local_player && g_local_player->m_net_object && g_local_player->m_net_object->m_object_id == net_id) - { - g_notification_service->push_warning("PROTECTIONS"_T.data(), - std::vformat("REMOVE_ALL_WEAPONS_ATTEMPT"_T, std::make_format_args(source_player->get_name()))); - g_pointers->m_send_event_ack(event_manager, source_player, target_player, event_index, event_handled_bitset); - return; - } - - buffer->Seek(0); - break; - } - case eNetworkEvents::GIVE_CONTROL_EVENT: - { - uint32_t timestamp = buffer->Read(32); - int count = buffer->Read(2); - bool all_objects_migrate_together = buffer->Read(1); - - if (count > 3) - { - count = 3; - } - - for (int i = 0; i < count; i++) - { - int net_id = buffer->Read(13); - eNetObjType object_type = buffer->Read(4); - int migration_type = buffer->Read(3); - - if (object_type < eNetObjType::NET_OBJ_TYPE_AUTOMOBILE || object_type > eNetObjType::NET_OBJ_TYPE_TRAIN) - { - notify::crash_blocked(source_player, "out of bounds give control type"); - g_pointers->m_send_event_ack(event_manager, source_player, target_player, event_index, event_handled_bitset); - return; - } - } - - buffer->Seek(0); - g.m_syncing_player = source_player; - break; - } - case eNetworkEvents::NETWORK_PLAY_SOUND_EVENT: - { - if (plyr && plyr->m_play_sound_rate_limit.process()) - { - if (plyr->m_play_sound_rate_limit.exceeded_last_process()) - { - notify::crash_blocked(source_player, "sound spam"); - } - g_pointers->m_send_event_ack(event_manager, source_player, target_player, event_index, event_handled_bitset); - return; - } - - bool is_entity = buffer->Read(1); - std::int16_t entity_net_id; - rage::fvector3 position; - std::uint32_t ref_hash; - - if (is_entity) - entity_net_id = buffer->Read(13); - else - { - position.x = buffer->ReadSignedFloat(19, 1337.0f); - position.y = buffer->ReadSignedFloat(19, 1337.0f); - position.z = buffer->ReadFloat(19, 1337.0f); - } - - bool has_ref = buffer->Read(1); - if (has_ref) - ref_hash = buffer->Read(32); - - std::uint32_t sound_hash = buffer->Read(32); - - if (sound_hash == RAGE_JOAAT("Remote_Ring") && plyr) - { - g.reactions.sound_spam.process(plyr); - return; - } - - buffer->Seek(0); - break; - } - case eNetworkEvents::EXPLOSION_EVENT: - { - scan_explosion_event(source_player, buffer); - break; - } - case eNetworkEvents::WEAPON_DAMAGE_EVENT: - { - scan_weapon_damage_event(source_player, buffer); - break; - } - default: break; - } - - return g_hooking->get_original()(event_manager, source_player, target_player, event_id, event_index, event_handled_bitset, buffer_size, buffer); - } -} +#include "fiber_pool.hpp" +#include "gta/enums.hpp" +#include "gta/net_game_event.hpp" +#include "gta/script_id.hpp" +#include "hooking.hpp" +#include "util/math.hpp" +#include "util/notify.hpp" +#include "util/toxic.hpp" + +#include +#include + +namespace big +{ + static void script_id_deserialize(CGameScriptId& id, rage::datBitBuffer& buffer) + { + id.m_hash = buffer.Read(32); + id.m_timestamp = buffer.Read(32); + + if (buffer.Read(1)) + id.m_position_hash = buffer.Read(32); + + if (buffer.Read(1)) + id.m_instance_id = buffer.Read(8); + } + + void scan_weapon_damage_event(CNetGamePlayer* player, rage::datBitBuffer* buffer) + { + uint8_t damageType; + uint32_t weaponType;// weaponHash + + bool overrideDefaultDamage; + bool hitEntityWeapon; + bool hitWeaponAmmoAttachment; + bool silenced; + + uint32_t damageFlags; + bool hasActionResult; + + uint32_t actionResultName; + uint16_t actionResultId; + uint32_t f104; + + uint32_t weaponDamage; + bool isNetTargetPos; + + rage::fvector3 localPos; + + bool f112; + + uint32_t damageTime; + bool willKill; + uint32_t f120; + bool hasVehicleData; + + uint16_t f112_1; + + uint16_t parentGlobalId;// Source entity? + uint16_t hitGlobalId; // Target entity? + + uint8_t tyreIndex; + uint8_t suspensionIndex; + uint8_t hitComponent; + + bool f133; + bool hasImpactDir; + + rage::fvector3 impactDir; + + damageType = buffer->Read(2); + weaponType = buffer->Read(32); + + overrideDefaultDamage = buffer->Read(1); + hitEntityWeapon = buffer->Read(1); + hitWeaponAmmoAttachment = buffer->Read(1); + silenced = buffer->Read(1); + + damageFlags = buffer->Read(24); + // (damageFlags >> 1) & 1 + hasActionResult = buffer->Read(1); + + if (hasActionResult) + { + actionResultName = buffer->Read(32); + actionResultId = buffer->Read(16); + f104 + = buffer->Read(32); + } + + if (overrideDefaultDamage) + { + weaponDamage = buffer->Read(17); + } + else + { + weaponDamage = 0; + } + + bool _f92 = buffer->Read(1); + + if (_f92) + { + buffer->Read(4); + } + + isNetTargetPos = buffer->Read(1); + + if (isNetTargetPos) + { + localPos.x = buffer->ReadSignedFloat(16, 55.f);// divisor: 0x425C0000 + localPos.y = buffer->ReadSignedFloat(16, 55.f); + localPos.z = buffer->ReadSignedFloat(16, 55.f); + } + + if (damageType == 3) + { + damageTime = buffer->Read(32); + willKill = buffer->Read(1); + + if (hasActionResult) + { + hitGlobalId = buffer->Read(13); + } + else + { + hitGlobalId = 0; + } + + f112 = buffer->Read(1); + + if (!f112) + { + f112_1 = buffer->Read(11); + } + else + { + f112_1 = buffer->Read(16); + } + } + else + { + parentGlobalId = buffer->Read(13);// +118 + hitGlobalId = buffer->Read(13);// +120 + } + + if (damageType < 2) + { + localPos.x = buffer->ReadSignedFloat(16, 55.f);// divisor: 0x425C0000 + localPos.y = buffer->ReadSignedFloat(16, 55.f); + localPos.z = buffer->ReadSignedFloat(16, 55.f); + + if (damageType == 1) + { + hasVehicleData = buffer->Read(1); + + if (hasVehicleData) + { + tyreIndex = buffer->Read(4);// +122 + suspensionIndex = buffer->Read(4);// +123 + } + } + } + else + { + hitComponent = buffer->Read(5);// +108 + } + + f133 = buffer->Read(1); + hasImpactDir = buffer->Read(1); + + if (hasImpactDir) + { + impactDir.x = buffer->ReadSignedFloat(16, 6.2831854820251f);// divisor: 0x40C90FDB + impactDir.y = buffer->ReadSignedFloat(16, 6.2831854820251f); + impactDir.z = buffer->ReadSignedFloat(16, 6.2831854820251f); + } + + buffer->Seek(0); + + // LOG(INFO) << localPos.x << " " << localPos.y << " " << localPos.z << ". " << math::distance_between_vectors(localPos, *g_local_player->m_navigation->get_position()) << " " << (g_local_player->m_net_object->m_object_id == hitGlobalId ? "TRUE" : "FALSE") << " " << damageType << " " << damageFlags; + + if (damageType == 3 && (damageFlags & (1 << 1)) == 0) + hitGlobalId = g_local_player ? g_local_player->m_net_object->m_object_id : 0; + + if (g.session.damage_karma && g_local_player && g_local_player->m_net_object + && (g_local_player->m_net_object->m_object_id == hitGlobalId + || math::distance_between_vectors(localPos, *g_local_player->m_navigation->get_position()) < 1.5f)) + { + int id = player->m_player_id; + g_fiber_pool->queue_job([id, hitComponent, overrideDefaultDamage, weaponType, weaponDamage, tyreIndex, suspensionIndex, damageFlags, actionResultName, actionResultId, f104, hitEntityWeapon, hitWeaponAmmoAttachment, silenced, hasImpactDir, impactDir, localPos] { + auto player = g_player_service->get_by_id(id); + + if (!player->is_valid() || !player->get_ped()) + return; + + g_pointers->m_send_network_damage(g_player_service->get_self()->get_ped(), + player->get_ped(), + (rage::fvector3*)&localPos, + hitComponent, + overrideDefaultDamage, + weaponType, + weaponDamage, + tyreIndex, + suspensionIndex, + damageFlags, + actionResultName, + actionResultId, + f104, + hitEntityWeapon, + hitWeaponAmmoAttachment, + silenced, + false, + player->get_ped()->m_navigation->get_position()); + }); + } + } + + void scan_explosion_event(CNetGamePlayer* player, rage::datBitBuffer* buffer) + { + uint16_t f186; + uint16_t f208; + int ownerNetId; + uint16_t f214; + eExplosionTag explosionType; + float damageScale; + + float posX; + float posY; + float posZ; + + bool f242; + uint16_t f104; + float cameraShake; + + bool isAudible; + bool f189; + bool isInvisible; + bool f126; + bool f241; + bool f243; + + uint16_t f210; + + float unkX; + float unkY; + float unkZ; + + bool f190; + bool f191; + + uint32_t f164; + + float posX224; + float posY224; + float posZ224; + + bool f240; + uint16_t f218; + bool f216; + + // clang-format off + + f186 = buffer->Read(16); + f208 = buffer->Read(13); + ownerNetId = buffer->Read(13); + f214 = buffer->Read(13); // 1604+ + explosionType = (eExplosionTag)buffer->ReadSigned(8);// 1604+ bit size + damageScale = buffer->Read(8) / 255.0f; + + posX = buffer->ReadSignedFloat(22, 27648.0f); + posY = buffer->ReadSignedFloat(22, 27648.0f); + posZ = buffer->ReadFloat(22, 4416.0f) - 1700.0f; + + f242 = buffer->Read(1); + f104 = buffer->Read(16); + cameraShake = buffer->Read(8) / 127.0f; + + isAudible = buffer->Read(1); + f189 = buffer->Read(1); + isInvisible = buffer->Read(1); + f126 = buffer->Read(1); + f241 = buffer->Read(1); + f243 = buffer->Read(1);// 1604+ + + f210 = buffer->Read(13); + + unkX = buffer->ReadSignedFloat(16, 1.1f); + unkY = buffer->ReadSignedFloat(16, 1.1f); + unkZ = buffer->ReadSignedFloat(16, 1.1f); + + f190 = buffer->Read(1); + f191 = buffer->Read(1); + f164 = buffer->Read(32); + + if (f242) + { + posX224 = buffer->ReadSignedFloat(31, 27648.0f); + posY224 = buffer->ReadSignedFloat(31, 27648.0f); + posZ224 = buffer->ReadFloat(31, 4416.0f) - 1700.0f; + } + else + { + posX224 = 0; + posY224 = 0; + posZ224 = 0; + } + + auto f168 = buffer->Read(32);// >= 1868: f_168 + + + f240 = buffer->Read(1); + if (f240) + { + f218 = buffer->Read(16); + + if (f191) + { + f216 = buffer->Read(8); + } + } + + buffer->Seek(0); + + auto object = g_pointers->m_get_net_object(*g_pointers->m_network_object_mgr, ownerNetId, true); + auto entity = object ? object->GetGameObject() : nullptr; + + auto offset_object = g_pointers->m_get_net_object(*g_pointers->m_network_object_mgr, f210, true); + + if (f208 == 0 && entity && entity->m_entity_type == 4 && reinterpret_cast(entity)->m_player_info + && player->m_player_info->m_ped && player->m_player_info->m_ped->m_net_object + && ownerNetId != player->m_player_info->m_ped->m_net_object->m_object_id && !offset_object) + { + g_notification_service->push_error("WARNING"_T.data(), + std::vformat("BLAMED_FOR_EXPLOSION"_T, + std::make_format_args(player->get_name(), + reinterpret_cast(entity)->m_player_info->m_net_player_data.m_name))); + session::add_infraction(g_player_service->get_by_id(player->m_player_id), Infraction::BLAME_EXPLOSION_DETECTED); + return; + } + + if (g.session.explosion_karma && g_local_player + && math::distance_between_vectors({posX, posY, posZ}, *g_local_player->m_navigation->get_position()) < 3.0f) + { + int id = player->m_player_id; + g_fiber_pool->queue_job([id, explosionType, damageScale, cameraShake, isAudible, isInvisible] { + toxic::blame_explode_player(g_player_service->get_self(), g_player_service->get_by_id(id), explosionType, damageScale, isAudible, isInvisible, cameraShake); + }); + } + + // clang-format on + } + + void hooks::received_event(rage::netEventMgr* event_manager, CNetGamePlayer* source_player, CNetGamePlayer* target_player, uint16_t event_id, int event_index, int event_handled_bitset, int buffer_size, rage::datBitBuffer* buffer) + { + if (event_id > 91u) + { + g_pointers->m_send_event_ack(event_manager, source_player, target_player, event_index, event_handled_bitset); + return; + } + + const auto event_name = *(char**)((DWORD64)event_manager + 8i64 * event_id + 243376); + if (event_name == nullptr || source_player == nullptr || source_player->m_player_id < 0 || source_player->m_player_id >= 32) + { + g_pointers->m_send_event_ack(event_manager, source_player, target_player, event_index, event_handled_bitset); + return; + } + + auto plyr = g_player_service->get_by_id(source_player->m_player_id); + + switch (static_cast(event_id)) + { + case eNetworkEvents::KICK_VOTES_EVENT: + { + std::uint32_t player_bitfield = buffer->Read(32); + if (player_bitfield & (1 << target_player->m_player_id)) + { + g.reactions.kick_vote.process(plyr); + } + buffer->Seek(0); + break; + } + case eNetworkEvents::NETWORK_INCREMENT_STAT_EVENT: + { + const auto increment_stat_event = std::make_unique(); + buffer->ReadDword(&increment_stat_event->m_stat, 0x20); + buffer->ReadDword(&increment_stat_event->m_amount, 0x20); + if (hooks::increment_stat_event(increment_stat_event.get(), source_player)) + { + g_pointers->m_send_event_ack(event_manager, source_player, target_player, event_index, event_handled_bitset); + return; + } + buffer->Seek(0); + break; + } + case eNetworkEvents::SCRIPT_ENTITY_STATE_CHANGE_EVENT: + { + uint16_t entity = buffer->Read(13); + auto type = buffer->Read(4); + uint32_t unk = buffer->Read(32); + if (type == ScriptEntityChangeType::SettingOfTaskVehicleTempAction) + { + uint16_t ped_id = buffer->Read(13); + uint32_t action = buffer->Read(8); + + if ((action >= 15 && action <= 18) || action == 33) + { + g_pointers->m_send_event_ack(event_manager, source_player, target_player, event_index, event_handled_bitset); + notify::crash_blocked(source_player, "vehicle temp action"); + return; + } + } + else if (type > ScriptEntityChangeType::SetVehicleExclusiveDriver || type < ScriptEntityChangeType::BlockingOfNonTemporaryEvents) + { + notify::crash_blocked(source_player, "invalid script entity change type"); + g_pointers->m_send_event_ack(event_manager, source_player, target_player, event_index, event_handled_bitset); + return; + } + buffer->Seek(0); + break; + } + case eNetworkEvents::SCRIPTED_GAME_EVENT: + { + const auto scripted_game_event = std::make_unique(); + buffer->ReadDword(&scripted_game_event->m_args_size, 32); + if (scripted_game_event->m_args_size - 1 <= 0x1AF) + buffer->ReadArray(&scripted_game_event->m_args, 8 * scripted_game_event->m_args_size); + + if (hooks::scripted_game_event(scripted_game_event.get(), source_player)) + { + g_pointers->m_send_event_ack(event_manager, source_player, target_player, event_index, event_handled_bitset); + + return; + } + buffer->Seek(0); + + break; + } + case eNetworkEvents::NETWORK_CLEAR_PED_TASKS_EVENT: + { + int net_id = buffer->Read(13); + + if (g_local_player && g_local_player->m_net_object && g_local_player->m_net_object->m_object_id == net_id) + { + g_pointers->m_send_event_ack(event_manager, source_player, target_player, event_index, event_handled_bitset); + g.reactions.clear_ped_tasks.process(plyr); + return; + } + + buffer->Seek(0); + break; + } + case eNetworkEvents::RAGDOLL_REQUEST_EVENT: + { + int net_id = buffer->Read(13); + + if (g_local_player && g_local_player->m_net_object && g_local_player->m_net_object->m_object_id == net_id) + { + g_pointers->m_send_event_ack(event_manager, source_player, target_player, event_index, event_handled_bitset); + g.reactions.remote_ragdoll.process(plyr); + return; + } + + buffer->Seek(0); + break; + } + // Don't block this event, we still want to report this player + // because if we still report others, our account seems less fishy + case eNetworkEvents::REPORT_CASH_SPAWN_EVENT: + { + uint32_t money; + + buffer->Seek(64); + buffer->ReadDword(&money, 32); + buffer->Seek(0); + + if (money >= 2000) + { + g.reactions.report_cash_spawn.process(plyr); + } + + break; + } + // player sending this event is a modder + case eNetworkEvents::REPORT_MYSELF_EVENT: + { + if (auto plyr = g_player_service->get_by_id(source_player->m_player_id)) + session::add_infraction(plyr, Infraction::TRIGGERED_ANTICHEAT); + + g.reactions.modder_detection.process(plyr); + break; + } + case eNetworkEvents::REQUEST_CONTROL_EVENT: + { + int net_id = buffer->Read(13); + if (g_local_player && g_local_player->m_vehicle && g_local_player->m_vehicle->m_net_object + && g_local_player->m_vehicle->m_net_object->m_object_id == net_id && g_local_player->m_vehicle->m_driver == g_local_player) + { + g_pointers->m_send_event_ack(event_manager, source_player, target_player, event_index, event_handled_bitset); + g.reactions.request_control_event.process(plyr); + return; + } + buffer->Seek(0); + break; + } + case eNetworkEvents::SCRIPT_WORLD_STATE_EVENT: + { + auto type = buffer->Read(4); + buffer->Read(1); + CGameScriptId id; + script_id_deserialize(id, *buffer); + + if (type == WorldStateDataType::Rope) + { + buffer->Read(9); // network rope id + buffer->Read(19);// pos x + buffer->Read(19);// pos y + buffer->Read(19);// pos z + buffer->Read(19);// rot x + buffer->Read(19);// rot y + buffer->Read(19);// rot z + buffer->Read(16);// length + int type = buffer->Read(4); + float initial_length = buffer->Read(16); + float min_length = buffer->Read(16); + + if (type == 0 || initial_length < min_length)// https://docs.fivem.net/natives/?_0xE832D760399EB220 + { + // most definitely a crash + LOG(INFO) << std::hex << std::uppercase << "0x" << id.m_hash; + notify::crash_blocked(source_player, "rope"); + g_pointers->m_send_event_ack(event_manager, source_player, target_player, event_index, event_handled_bitset); + return; + } + } + else if (type == WorldStateDataType::PopGroupOverride) + { + int pop_schedule = buffer->ReadSigned(8);// Pop Schedule + int pop_group = buffer->Read(32); // Pop Group + int percentage = buffer->Read(7); // Percentage + + if (pop_group == 0 && (percentage == 0 || percentage == 103)) + { + notify::crash_blocked(source_player, "pop group override"); + g_pointers->m_send_event_ack(event_manager, source_player, target_player, event_index, event_handled_bitset); + return; + } + } + else if (type > WorldStateDataType::VehiclePlayerLocking || type < WorldStateDataType::CarGen) + { + notify::crash_blocked(source_player, "invalid world state type"); + g_pointers->m_send_event_ack(event_manager, source_player, target_player, event_index, event_handled_bitset); + return; + } + + buffer->Seek(0); + break; + } + case eNetworkEvents::REMOVE_WEAPON_EVENT: + { + int net_id = buffer->Read(13); + uint32_t hash = buffer->Read(32); + + if (hash == RAGE_JOAAT("WEAPON_UNARMED")) + { + notify::crash_blocked(source_player, "remove unarmed"); + g_pointers->m_send_event_ack(event_manager, source_player, target_player, event_index, event_handled_bitset); + return; + } + + if (g_local_player && g_local_player->m_net_object && g_local_player->m_net_object->m_object_id == net_id) + { + g_notification_service->push_warning("PROTECTIONS"_T.data(), + std::vformat("REMOVE_WEAPON_ATTEMPT"_T, std::make_format_args(source_player->get_name()))); + g_pointers->m_send_event_ack(event_manager, source_player, target_player, event_index, event_handled_bitset); + return; + } + + buffer->Seek(0); + break; + } + case eNetworkEvents::REMOVE_ALL_WEAPONS_EVENT: + { + int net_id = buffer->Read(13); + + if (g_local_player && g_local_player->m_net_object && g_local_player->m_net_object->m_object_id == net_id) + { + g_notification_service->push_warning("PROTECTIONS"_T.data(), + std::vformat("REMOVE_ALL_WEAPONS_ATTEMPT"_T, std::make_format_args(source_player->get_name()))); + g_pointers->m_send_event_ack(event_manager, source_player, target_player, event_index, event_handled_bitset); + return; + } + + buffer->Seek(0); + break; + } + case eNetworkEvents::GIVE_CONTROL_EVENT: + { + uint32_t timestamp = buffer->Read(32); + int count = buffer->Read(2); + bool all_objects_migrate_together = buffer->Read(1); + + if (count > 3) + { + count = 3; + } + + for (int i = 0; i < count; i++) + { + int net_id = buffer->Read(13); + eNetObjType object_type = buffer->Read(4); + int migration_type = buffer->Read(3); + + if (object_type < eNetObjType::NET_OBJ_TYPE_AUTOMOBILE || object_type > eNetObjType::NET_OBJ_TYPE_TRAIN) + { + notify::crash_blocked(source_player, "out of bounds give control type"); + g_pointers->m_send_event_ack(event_manager, source_player, target_player, event_index, event_handled_bitset); + return; + } + } + + buffer->Seek(0); + g.m_syncing_player = source_player; + break; + } + case eNetworkEvents::NETWORK_PLAY_SOUND_EVENT: + { + if (plyr && plyr->m_play_sound_rate_limit.process()) + { + if (plyr->m_play_sound_rate_limit.exceeded_last_process()) + { + notify::crash_blocked(source_player, "sound spam"); + } + g_pointers->m_send_event_ack(event_manager, source_player, target_player, event_index, event_handled_bitset); + return; + } + + bool is_entity = buffer->Read(1); + std::int16_t entity_net_id; + rage::fvector3 position; + std::uint32_t ref_hash; + + if (is_entity) + entity_net_id = buffer->Read(13); + else + { + position.x = buffer->ReadSignedFloat(19, 1337.0f); + position.y = buffer->ReadSignedFloat(19, 1337.0f); + position.z = buffer->ReadFloat(19, 1337.0f); + } + + bool has_ref = buffer->Read(1); + if (has_ref) + ref_hash = buffer->Read(32); + + std::uint32_t sound_hash = buffer->Read(32); + + if (sound_hash == RAGE_JOAAT("Remote_Ring") && plyr) + { + g.reactions.sound_spam.process(plyr); + return; + } + + buffer->Seek(0); + break; + } + case eNetworkEvents::EXPLOSION_EVENT: + { + scan_explosion_event(source_player, buffer); + break; + } + case eNetworkEvents::WEAPON_DAMAGE_EVENT: + { + scan_weapon_damage_event(source_player, buffer); + break; + } + default: break; + } + + return g_hooking->get_original()(event_manager, source_player, target_player, event_id, event_index, event_handled_bitset, buffer_size, buffer); + } +} diff --git a/src/services/context_menu/context_menu_service.cpp b/src/services/context_menu/context_menu_service.cpp index 365b26d6..513bb5f1 100644 --- a/src/services/context_menu/context_menu_service.cpp +++ b/src/services/context_menu/context_menu_service.cpp @@ -1,11 +1,11 @@ #include "context_menu_service.hpp" +#include "fiber_pool.hpp" #include "gta/replay.hpp" #include "gui.hpp" #include "natives.hpp" #include "pointers.hpp" #include "util/misc.hpp" -#include "fiber_pool.hpp" namespace big { @@ -113,19 +113,19 @@ namespace big double context_menu_service::distance_to_middle_of_screen(const rage::fvector2& screen_pos) { - double cumulative_distance{}; + double cum_dist{}; if (screen_pos.x > 0.5) - cumulative_distance += screen_pos.x - 0.5; + cum_dist += screen_pos.x - 0.5; else - cumulative_distance += 0.5 - screen_pos.x; + cum_dist += 0.5 - screen_pos.x; if (screen_pos.y > 0.5) - cumulative_distance += screen_pos.y - 0.5; + cum_dist += screen_pos.y - 0.5; else - cumulative_distance += 0.5 - screen_pos.y; + cum_dist += 0.5 - screen_pos.y; - return cumulative_distance; + return cum_dist; } s_context_menu* context_menu_service::get_context_menu() @@ -142,6 +142,7 @@ namespace big } return &options.at(ContextEntityType::OBJECT); } + case eModelType::OnlineOnlyPed: case eModelType::Ped: { if (const auto ped = reinterpret_cast(m_pointer); ped) @@ -200,48 +201,52 @@ namespace big if (veh_interface && ped_interface && obj_interface) { - const auto veh_interface_size = veh_interface->m_max_vehicles; - const auto ped_interface_size = ped_interface->m_max_peds; - const auto obj_interface_size = obj_interface->m_max_objects; - const auto all_entities = std::make_unique(veh_interface_size + ped_interface_size + obj_interface_size); + double distance = 1; - const auto ptr = all_entities.get(); - std::uint32_t offset = 0; - std::copy(ped_interface->m_ped_list->m_peds, ped_interface->m_ped_list->m_peds + ped_interface_size, ptr); - offset += ped_interface_size; - - std::copy(veh_interface->m_vehicle_list->m_vehicles, veh_interface->m_vehicle_list->m_vehicles + veh_interface_size, ptr + offset); - offset += veh_interface_size; - - std::copy(obj_interface->m_object_list->m_objects, obj_interface->m_object_list->m_objects + obj_interface_size, ptr + offset); - offset += obj_interface_size; - - double distance = 1; - bool got_an_entity = false; - rage::fvector2 screen_pos{}; - for (std::uint32_t i = 0; i < offset; i++) + const auto get_closest_to_center = [this, &distance](auto entity_list) -> auto { - if (!all_entities[i].m_entity_ptr) - continue; - - const auto temp_pointer = all_entities[i].m_entity_ptr; - const auto temp_handle = g_pointers->m_ptr_to_handle(temp_pointer); - if (!temp_pointer->m_navigation) - continue; - - const auto pos = *temp_pointer->m_navigation->get_position(); - HUD::GET_HUD_SCREEN_POSITION_FROM_WORLD_POSITION(pos.x, pos.y, pos.z, &screen_pos.x, &screen_pos.y); - if (distance_to_middle_of_screen(screen_pos) < distance && ENTITY::HAS_ENTITY_CLEAR_LOS_TO_ENTITY(PLAYER::PLAYER_PED_ID(), temp_handle, 17) && temp_handle != PLAYER::PLAYER_PED_ID()) + rage::fvector2 screen_pos{}; + bool got_an_entity = false; + for (const auto entity : *entity_list) { - m_handle = temp_handle; - m_pointer = temp_pointer; - distance = distance_to_middle_of_screen(screen_pos); - got_an_entity = true; + const auto temp_pointer = entity.m_entity_ptr; + if (!temp_pointer || !temp_pointer->m_navigation) + continue; + const auto temp_handle = g_pointers->m_ptr_to_handle(temp_pointer); + + const auto pos = temp_pointer->m_navigation->get_position(); + HUD::GET_HUD_SCREEN_POSITION_FROM_WORLD_POSITION(pos->x, + pos->y, + pos->z, + &screen_pos.x, + &screen_pos.y); + + const auto distance_from_middle = distance_to_middle_of_screen(screen_pos); + if (distance_from_middle < distance && ENTITY::HAS_ENTITY_CLEAR_LOS_TO_ENTITY(self::ped, temp_handle, 17) && temp_handle != self::ped) + { + m_handle = temp_handle; + m_pointer = temp_pointer; + distance = distance_from_middle; + got_an_entity = true; + } } - } + return got_an_entity; + }; + + // I'm using bitwise OR instead or || to avoid compiler optimisation, all functions HAVE to execute + auto got_an_entity = get_closest_to_center(veh_interface->m_vehicle_list); + got_an_entity |= get_closest_to_center(ped_interface->m_ped_list); + got_an_entity |= get_closest_to_center(obj_interface->m_object_list); if (got_an_entity) { + // if the ped is driving a vehicle take their vehicle instead of the ped (aka. prevent jank) + if ((m_pointer->m_model_info->m_model_type == eModelType::Ped || m_pointer->m_model_info->m_model_type == eModelType::OnlineOnlyPed) + && reinterpret_cast(m_pointer)->m_vehicle) + { + m_pointer = reinterpret_cast(m_pointer)->m_vehicle; + m_handle = g_pointers->m_ptr_to_handle(m_pointer); + } fill_model_bounding_box_screen_space(); } } @@ -303,12 +308,6 @@ namespace big continue; } - if (g_gui->is_open()) - { - script::get_current()->yield(); - continue; - } - if (PAD::IS_DISABLED_CONTROL_JUST_RELEASED(0, (int)ControllerInputs::INPUT_VEH_DUCK)) { g_context_menu_service->enabled = !g_context_menu_service->enabled; @@ -326,25 +325,23 @@ namespace big script::get_current()->yield(); continue; } - else + + if (PAD::IS_DISABLED_CONTROL_JUST_PRESSED(0, (int)ControllerInputs::INPUT_WEAPON_WHEEL_NEXT)) + cm->current_option = cm->options.size() <= cm->current_option + 1 ? 0 : cm->current_option + 1; + if (PAD::IS_DISABLED_CONTROL_JUST_PRESSED(0, (int)ControllerInputs::INPUT_WEAPON_WHEEL_PREV)) + cm->current_option = 0 > cm->current_option - 1 ? static_cast(cm->options.size()) - 1 : cm->current_option - 1; + + if (PAD::IS_DISABLED_CONTROL_JUST_PRESSED(0, (int)ControllerInputs::INPUT_ATTACK) || PAD::IS_DISABLED_CONTROL_JUST_PRESSED(0, (int)ControllerInputs::INPUT_SPECIAL_ABILITY)) { - if (PAD::IS_DISABLED_CONTROL_JUST_PRESSED(0, (int)ControllerInputs::INPUT_WEAPON_WHEEL_NEXT)) - cm->current_option = cm->options.size() <= cm->current_option + 1 ? 0 : cm->current_option + 1; - if (PAD::IS_DISABLED_CONTROL_JUST_PRESSED(0, (int)ControllerInputs::INPUT_WEAPON_WHEEL_PREV)) - cm->current_option = 0 > cm->current_option - 1 ? static_cast(cm->options.size()) - 1 : cm->current_option - 1; - - if (PAD::IS_DISABLED_CONTROL_JUST_PRESSED(0, (int)ControllerInputs::INPUT_ATTACK) || PAD::IS_DISABLED_CONTROL_JUST_PRESSED(0, (int)ControllerInputs::INPUT_SPECIAL_ABILITY)) + if (!g_context_menu_service->m_pointer) { - if (!g_context_menu_service->m_pointer) - { - continue; - } - - g_fiber_pool->queue_job([cm] { - cm->options.at(cm->current_option).command(); - }); - + script::get_current()->yield(); + continue; } + + g_fiber_pool->queue_job([cm] { + cm->options.at(cm->current_option).command(); + }); } } diff --git a/src/util/entity.hpp b/src/util/entity.hpp index 16318138..fda26438 100644 --- a/src/util/entity.hpp +++ b/src/util/entity.hpp @@ -209,14 +209,11 @@ namespace big::entity Entity closest_entity{}; float distance = 1; - //if (!vehicleInterface || !pedInterface) - // return 0; - auto replayInterface = *g_pointers->m_replay_interface; auto vehicleInterface = replayInterface->m_vehicle_interface; auto pedInterface = replayInterface->m_ped_interface; - for (auto veh : vehicleInterface->m_vehicle_list->m_vehicles) + for (const auto veh : (*vehicleInterface->m_vehicle_list)) { if (veh.m_entity_ptr) { @@ -233,7 +230,7 @@ namespace big::entity } } - for (auto ped : pedInterface->m_ped_list->m_peds) + for (auto ped : *pedInterface->m_ped_list) { if (ped.m_entity_ptr) { diff --git a/src/util/vehicle.hpp b/src/util/vehicle.hpp index f9d53cd5..90ae01d5 100644 --- a/src/util/vehicle.hpp +++ b/src/util/vehicle.hpp @@ -108,15 +108,11 @@ namespace big::vehicle float min_dist = FLT_MAX; int32_t m_handle = 0; - for (int32_t i = 0; i < veh_interface_size; i++) + for (const auto veh_entity : *veh_interface->m_vehicle_list) { - auto veh_entity = veh_interface->m_vehicle_list->m_vehicles[i]; - auto veh_ptr = veh_entity.m_entity_ptr; - + const auto veh_ptr = veh_entity.m_entity_ptr; if (!veh_ptr || !veh_ptr->m_navigation) - { continue; - } auto veh_pos_arr = *veh_ptr->m_navigation->get_position(); Vector3 veh_pos(veh_pos_arr.x, veh_pos_arr.y, veh_pos_arr.z);