From 64b47779e8ef330271638e64928ecfa4f60194af Mon Sep 17 00:00:00 2001 From: maybegreat48 <96936658+maybegreat48@users.noreply.github.com> Date: Mon, 21 Nov 2022 15:42:12 +0000 Subject: [PATCH] Lessen breakup kicks and more (#625) --- scripts/gtav-classes.cmake | 2 +- src/backend/backend.cpp | 7 +- src/backend/looped/looped.hpp | 3 +- src/backend/looped/player/good_options.cpp | 67 +++++++++ .../looped/player/player_never_wanted.cpp | 14 -- .../looped/player/remote_control_vehicle.cpp | 50 +++++++ .../looped/system/force_session_host.cpp | 2 +- src/core/data/infractions.hpp | 6 +- src/core/globals.hpp | 25 +++- src/core/scr_globals.hpp | 40 ++++++ src/gta/fwddec.hpp | 1 - src/gta/net_game_event.hpp | 45 +++++- src/gta/script_handler.hpp | 80 +++++++++++ src/hooking.cpp | 3 + src/hooking.hpp | 5 + src/hooks/info/get_network_event_data.cpp | 2 + src/hooks/misc/send_chat_net_message.cpp | 26 ++++ .../assign_physical_index.cpp | 5 +- .../player_management/network_player_mgr.cpp | 1 + .../protections/add_player_to_session.cpp | 55 +++++++ src/hooks/protections/receive_net_message.cpp | 50 +++---- src/hooks/protections/received_event.cpp | 135 ++++++++++++++++++ src/hooks/spoofing/send_net_info_to_lobby.cpp | 24 ++++ src/native_hooks/all_scripts.hpp | 7 + src/native_hooks/am_launcher.hpp | 44 ++++++ src/native_hooks/freemode.hpp | 12 ++ src/native_hooks/native_hooks.cpp | 4 + src/pointers.cpp | 12 ++ src/pointers.hpp | 3 + src/script_hook.cpp | 4 +- src/services/mobile/mobile_service.cpp | 4 +- .../player_database_service.cpp | 2 +- src/services/players/player.hpp | 11 +- src/services/players/player_service.cpp | 25 ++-- src/services/players/player_service.hpp | 5 +- src/services/players/rate_limiter.hpp | 40 ++++++ src/util/entity.hpp | 19 +-- src/util/globals.hpp | 30 ++-- src/util/mobile.hpp | 33 +++-- src/util/scripts.hpp | 108 +++++++++++++- src/util/session.hpp | 19 +-- src/util/spam.hpp | 52 +++++++ src/util/vehicle.hpp | 77 +++++++--- src/views/network/view_session.cpp | 51 +++++++ src/views/players/view_player.cpp | 42 +++++- .../settings/view_protection_settings.cpp | 3 + 46 files changed, 1109 insertions(+), 146 deletions(-) create mode 100644 src/backend/looped/player/good_options.cpp delete mode 100644 src/backend/looped/player/player_never_wanted.cpp create mode 100644 src/backend/looped/player/remote_control_vehicle.cpp create mode 100644 src/core/scr_globals.hpp create mode 100644 src/hooks/misc/send_chat_net_message.cpp create mode 100644 src/hooks/protections/add_player_to_session.cpp create mode 100644 src/native_hooks/am_launcher.hpp create mode 100644 src/services/players/rate_limiter.hpp create mode 100644 src/util/spam.hpp diff --git a/scripts/gtav-classes.cmake b/scripts/gtav-classes.cmake index 2e8d618d..0f2811d7 100644 --- a/scripts/gtav-classes.cmake +++ b/scripts/gtav-classes.cmake @@ -3,7 +3,7 @@ include(FetchContent) FetchContent_Declare( gtav_classes GIT_REPOSITORY https://github.com/Yimura/GTAV-Classes.git - GIT_TAG 1dc66fb37fec895c96c2b1e4944e382a83c5e993 + GIT_TAG 16f85bea73691623d1a43c4a912f94f93e509597 GIT_PROGRESS TRUE CONFIGURE_COMMAND "" BUILD_COMMAND "" diff --git a/src/backend/backend.cpp b/src/backend/backend.cpp index 75259f74..ea1be225 100644 --- a/src/backend/backend.cpp +++ b/src/backend/backend.cpp @@ -126,12 +126,9 @@ namespace big while (g_running) { - g_player_service->iterate([](const player_entry &entry) - { - looped::player_never_wanted(entry.second); - }); - + looped::player_good_options(); looped::player_spectate(); + looped::player_remote_control_vehicle(); script::get_current()->yield(); } diff --git a/src/backend/looped/looped.hpp b/src/backend/looped/looped.hpp index b8707dd4..3a0f0133 100644 --- a/src/backend/looped/looped.hpp +++ b/src/backend/looped/looped.hpp @@ -15,8 +15,9 @@ namespace big static void tunables_disable_phone(); - static void player_never_wanted(const player_ptr &player); + static void player_good_options(); static void player_spectate(); + static void player_remote_control_vehicle(); static void protections_replay_interface(); diff --git a/src/backend/looped/player/good_options.cpp b/src/backend/looped/player/good_options.cpp new file mode 100644 index 00000000..9d55927f --- /dev/null +++ b/src/backend/looped/player/good_options.cpp @@ -0,0 +1,67 @@ +#include "gta/PickupRewards.h" +#include "backend/looped/looped.hpp" +#include "services/players/player_service.hpp" +#include "util/globals.hpp" +#include "util/misc.hpp" + +namespace big +{ + // rate limit script events to prevent crashes + static int offRadarPlayer = 0; + static int neverWantedPlayer = 0; + void looped::player_good_options() + { + if (!NETWORK::NETWORK_IS_SESSION_STARTED()) + return; + + offRadarPlayer++; + if (offRadarPlayer > 32) + offRadarPlayer = 0; + + neverWantedPlayer++; + if (neverWantedPlayer > 32) + neverWantedPlayer = 0; + + g_player_service->iterate([](const player_entry& entry) + { + if ((g->session.off_radar_all || entry.second->off_radar) && offRadarPlayer == entry.second->id()) + globals::give_remote_otr(entry.second->id()); + }); + + g_player_service->iterate([](const player_entry& entry) + { + if ((g->session.never_wanted_all || entry.second->never_wanted) && PLAYER::GET_PLAYER_WANTED_LEVEL(entry.second->id()) > 0 && neverWantedPlayer == entry.second->id()) + globals::clear_wanted_player(entry.second->id()); + }); + + if (g->session.semi_godmode_all) + { + g_pointers->m_give_pickup_rewards(-1, REWARD_HEALTH); + g_pointers->m_give_pickup_rewards(-1, REWARD_ARMOUR); + } + else + { + g_player_service->iterate([](const player_entry& entry) + { + if (entry.second->semi_godmode) + { + if (CPed* ped = entry.second->get_ped()) + { + if (ped->m_maxhealth == 0 || ped->m_health == 0 || misc::has_bit_set((int*)&ped->m_damage_bits, 8)) + return; + + if (ped->m_health < ped->m_maxhealth) + { + g_pointers->m_give_pickup_rewards(1 << entry.second->id(), REWARD_HEALTH); + } + + if (ped->m_armor < 50.0f) + { + g_pointers->m_give_pickup_rewards(1 << entry.second->id(), REWARD_ARMOUR); + } + } + } + }); + } + } +} diff --git a/src/backend/looped/player/player_never_wanted.cpp b/src/backend/looped/player/player_never_wanted.cpp deleted file mode 100644 index cc3ae7df..00000000 --- a/src/backend/looped/player/player_never_wanted.cpp +++ /dev/null @@ -1,14 +0,0 @@ -#include "backend/looped/looped.hpp" -#include "services/players/player_service.hpp" -#include "util/globals.hpp" - -namespace big -{ - void looped::player_never_wanted(const player_ptr &player) - { - if (player->never_wanted) - { - globals::clear_wanted_player(player->id()); - } - } -} diff --git a/src/backend/looped/player/remote_control_vehicle.cpp b/src/backend/looped/player/remote_control_vehicle.cpp new file mode 100644 index 00000000..23b09c49 --- /dev/null +++ b/src/backend/looped/player/remote_control_vehicle.cpp @@ -0,0 +1,50 @@ +#include "backend/looped/looped.hpp" +#include "pointers.hpp" +#include "natives.hpp" +#include "util/entity.hpp" +#include "fiber_pool.hpp" + +namespace big +{ + void looped::player_remote_control_vehicle() + { + if (g->m_remote_controller_vehicle == -1) + return; + + if (!ENTITY::DOES_ENTITY_EXIST(g->m_remote_controlled_vehicle)) + { + g->m_remote_controlled_vehicle = -1; + g->m_remote_controlled_vehicle = -1; + return; + } + + if (!ENTITY::DOES_ENTITY_EXIST(g->m_remote_controller_vehicle)) + { + g->m_remote_controlled_vehicle = -1; + g->m_remote_controlled_vehicle = -1; + return; + } + + if (VEHICLE::IS_VEHICLE_SEAT_FREE(g->m_remote_controller_vehicle, -1, TRUE)) + { + auto controlled = g->m_remote_controlled_vehicle; + auto controller = g->m_remote_controller_vehicle; + g_fiber_pool->queue_job([controlled, controller] + { + if (entity::take_control_of(controlled)) + { + ENTITY::SET_ENTITY_COLLISION(g->m_remote_controlled_vehicle, TRUE, TRUE); + ENTITY::DETACH_ENTITY(controlled, TRUE, TRUE); + VEHICLE::SET_VEHICLE_DOORS_LOCKED(controlled, 0); + VEHICLE::SET_VEHICLE_DOORS_LOCKED_FOR_ALL_PLAYERS(controlled, FALSE); + ENTITY::SET_ENTITY_INVINCIBLE(controlled, FALSE); + entity::delete_entity(controller); + } + }); + + + g->m_remote_controller_vehicle = -1; + g->m_remote_controlled_vehicle = -1; + } + } +}; \ No newline at end of file diff --git a/src/backend/looped/system/force_session_host.cpp b/src/backend/looped/system/force_session_host.cpp index c7caf76e..8abc97c8 100644 --- a/src/backend/looped/system/force_session_host.cpp +++ b/src/backend/looped/system/force_session_host.cpp @@ -13,7 +13,7 @@ namespace big std::uint64_t host_token; g_pointers->m_generate_uuid(&host_token); - host_token = g->session.force_session_host ? 1 : host_token; + host_token = g->session.force_session_host ? (rand() % 10000) : host_token; *g_pointers->m_host_token = host_token; diff --git a/src/core/data/infractions.hpp b/src/core/data/infractions.hpp index effb1a24..54f5c744 100644 --- a/src/core/data/infractions.hpp +++ b/src/core/data/infractions.hpp @@ -12,7 +12,8 @@ namespace big SPOOFED_ROCKSTAR_ID, TRIGGERED_ANTICHEAT, TRIED_CRASH_PLAYER, - TRIED_KICK_PLAYER + TRIED_KICK_PLAYER, + BLAME_EXPLOSION_DETECTED }; inline std::unordered_map infraction_desc = @@ -23,6 +24,7 @@ namespace big {Infraction::SPOOFED_ROCKSTAR_ID, "Had spoofed RID"}, {Infraction::TRIGGERED_ANTICHEAT, "Triggered Rockstar's anticheat"}, {Infraction::TRIED_CRASH_PLAYER, "Tried to crash you"}, - {Infraction::TRIED_KICK_PLAYER, "Tried to kick you"} + {Infraction::TRIED_KICK_PLAYER, "Tried to kick you"}, + {Infraction::BLAME_EXPLOSION_DETECTED, "Tried to blame someone for their explosion"} }; } \ No newline at end of file diff --git a/src/core/globals.hpp b/src/core/globals.hpp index 8c3700c7..4d4327f9 100644 --- a/src/core/globals.hpp +++ b/src/core/globals.hpp @@ -146,6 +146,7 @@ namespace big script_events script_events{}; bool script_host_kick = true; bool rid_join = false; + bool lessen_breakups = false; // disabled by default due to anticheat concerns }; struct self @@ -200,6 +201,14 @@ namespace big bool player_magnet_enabled = false; int player_magnet_count = 32; bool is_team = false; + bool name_spoof_enabled = false; + bool advertise_menu = false; + std::string spoofed_name = ""; + + // not to be saved + bool never_wanted_all = false; + bool off_radar_all = false; + bool semi_godmode_all = false; }; struct settings { @@ -406,6 +415,10 @@ namespace big int player_count = 0; CNetGamePlayer* m_syncing_player = nullptr; + std::unordered_map m_spoofed_peer_ids; + + int m_remote_controller_vehicle = -1; + int m_remote_controlled_vehicle = -1; debug debug{}; tunables tunables{}; @@ -573,6 +586,7 @@ namespace big this->protections.script_host_kick = j["protections"]["script_host_kick"]; this->protections.rid_join = j["protections"]["rid_join"]; + this->protections.lessen_breakups = j["protections"]["lessen_breakups"]; this->tunables.disable_phone = j["tunables"]["disable_phone"]; this->tunables.no_idle_kick = j["tunables"]["no_idle_kick"]; @@ -612,6 +626,9 @@ namespace big this->session.player_magnet_enabled = j["session"]["player_magnet_enabled"]; this->session.player_magnet_count = j["session"]["player_magnet_count"]; this->session.is_team = j["session"]["is_team"]; + this->session.name_spoof_enabled = j["session"]["name_spoof_enabled"]; + this->session.advertise_menu = j["session"]["advertise_menu"]; + this->session.spoofed_name = j["session"]["spoofed_name"]; this->settings.dev_dlc = j["settings"]["dev_dlc"]; this->settings.hotkeys.menu_toggle = j["settings"]["hotkeys"]["menu_toggle"]; @@ -861,7 +878,8 @@ namespace big }, { "script_host_kick", g->protections.script_host_kick }, - { "rid_join", g->protections.rid_join } + { "rid_join", g->protections.rid_join }, + { "lessen_breakups", g->protections.lessen_breakups } } }, { @@ -931,7 +949,10 @@ namespace big { "force_session_host", this->session.force_session_host }, { "player_magnet_enabled", this->session.player_magnet_enabled }, { "player_magnet_count", this->session.player_magnet_count }, - { "is_team", this->session.is_team } + { "is_team", this->session.is_team }, + { "name_spoof_enabled", this->session.name_spoof_enabled }, + { "advertise_menu", this->session.advertise_menu }, + { "spoofed_name", this->session.spoofed_name } } }, { diff --git a/src/core/scr_globals.hpp b/src/core/scr_globals.hpp new file mode 100644 index 00000000..7f40d04c --- /dev/null +++ b/src/core/scr_globals.hpp @@ -0,0 +1,40 @@ +#pragma once +#include "script_global.hpp" + +namespace big::scr_globals +{ + namespace size + { + constexpr int globalplayer_bd = 453; + constexpr int gpbd_fm_3 = 599; + constexpr int gpbd_fm_1 = 888; + } + + static inline script_global gsbd(2680265); + static inline script_global gsbd_fm(1835502); + static inline script_global gsbd_kicking(1883751); + static inline script_global gsbd_fm_events(1920255); + static inline script_global gsbd_block_c(2683918); + + static inline script_global globalplayer_bd(2689235); + static inline script_global gpbd_fm_3(1892703); + static inline script_global gpbd_fm_1(1853348); + + static inline script_global launcher_global(2779753); + + static inline script_global sp(113386); + static inline script_global mission_definition(91229); + + static inline script_global creator_job_metadata(4718592); + static inline script_global terminate_creator(1574607); // NETWORK::NETWORK_BAIL(1, 0, 0); fm_*_creator + static inline script_global switch_struct(1574632); + static inline script_global mission_creator_radar_follows_camera(2621443); + static inline script_global mission_creator_exited(1574530); + + static inline script_global in_multiplayer(78319); // g_bInMultiplayer + + static inline script_global vehicle_global = script_global(1585857); + static inline script_global mechanic_global = script_global(2815059); + + static inline script_global spawn_global = script_global(2725439); +} \ No newline at end of file diff --git a/src/gta/fwddec.hpp b/src/gta/fwddec.hpp index ded77337..2383089c 100644 --- a/src/gta/fwddec.hpp +++ b/src/gta/fwddec.hpp @@ -59,7 +59,6 @@ class CGameScriptHandlerNetwork; class CGameScriptHandlerMgr; class CEntity; -class CDynamicEntity; class CPhysical; class CObject; diff --git a/src/gta/net_game_event.hpp b/src/gta/net_game_event.hpp index b08ac71b..8796b828 100644 --- a/src/gta/net_game_event.hpp +++ b/src/gta/net_game_event.hpp @@ -211,6 +211,49 @@ namespace rage WriteQWord((uint64_t)data, length); } + + template + inline void WriteSigned(int length, T data) + { + int sign = data < 0; + int signEx = (data < 0) ? 0xFFFFFFFF : 0; + int d = (data ^ signEx); + + Write(1, sign); + Write(length - 1, d); + } + + inline float ReadFloat(int length, float divisor) + { + auto integer = Read(length); + + float max = (1 << length) - 1; + return ((float)integer / max) * divisor; + } + + inline void WriteFloat(int length, float divisor, float value) + { + float max = (1 << length) - 1; + int integer = (int)((value / divisor) * max); + + Write(length, integer); + } + + inline float ReadSignedFloat(int length, float divisor) + { + auto integer = ReadSigned(length); + + float max = (1 << (length - 1)) - 1; + return ((float)integer / max) * divisor; + } + + inline void WriteSignedFloat(int length, float divisor, float value) + { + float max = (1 << (length - 1)) - 1; + int integer = (int)((value / divisor) * max); + + WriteSigned(length, integer); + } public: void* m_data; //0x0000 uint32_t m_bitOffset; //0x0008 @@ -376,7 +419,7 @@ namespace rage virtual __int64 get_type() = 0; virtual void unk_0x20() = 0; virtual void unk_0x28() = 0; - virtual bool get_extra_information(__int64* info_array, int check) = 0; + virtual bool get_extra_information(void* info_array, int check) = 0; virtual void unk_0x38() = 0; }; diff --git a/src/gta/script_handler.hpp b/src/gta/script_handler.hpp index 7450c655..e8078e00 100644 --- a/src/gta/script_handler.hpp +++ b/src/gta/script_handler.hpp @@ -179,6 +179,86 @@ class CGameScriptHandlerMgr : public rage::scriptHandlerMgr { }; +class CGameScriptHandlerNetComponent +{ +public: + virtual ~CGameScriptHandlerNetComponent() = default; + + virtual bool _0x08(void*) = 0; + + virtual void _0x10(CNetGamePlayer*) = 0; // creates a scriptId? + + virtual void* player_left(CNetGamePlayer* player) = 0; + + virtual void* send_host_migration_event(CNetGamePlayer* player) = 0; + + virtual void* player_joined(void**, void* msg_ctx) = 0; + + virtual void* player_joined_ack(void**, void* msg_ctx) = 0; + + virtual bool _0x38(void*, void*) = 0; // join_script? + + virtual void* _0x40(void*, void*) = 0; + + virtual void* _0x48(void*, void*, void*) = 0; + + virtual void* _0x50(void*, void*) = 0; + + virtual void* _0x58(void*, void*) = 0; + + virtual void* _0x60(void*, void*) = 0; + + virtual void* _0x68(void*, void*) = 0; + + virtual void _0x70(void*, void*) = 0; + + virtual void _0x78(void*, void*) = 0; + + virtual short _0x80(void*, void*) = 0; + + virtual void* _0x88(void*, void*) = 0; + + virtual void* _0x90(void*, void*) = 0; // HOST_MIGRATION_FAILED + + virtual bool _0x98(void*, void*) = 0; + + virtual void* _0xA0(void*, void*) = 0; + + virtual void* _0xA8(void*, void*) = 0; + + virtual short _0xB0(void*, void*) = 0; + + virtual bool register_host_broadcast_data(void* data, int size, char* a3) = 0; + + virtual bool register_player_broadcast_data(int a1, int size, bool a3) = 0; + + virtual bool _0xC8() = 0; // something to do to joining session + + virtual bool _0xD0() = 0; + + virtual bool add_player_to_script(CNetGamePlayer* player, short* outParticipantID, short* outSlot, int* outFailReason) = 0; + + virtual bool add_player_to_script_internal(CNetGamePlayer* player, short participantID, short slot) = 0; // player aka participant + + virtual bool remove_player_from_script(CNetGamePlayer* player) = 0; + + virtual void* player_left_impl(CNetGamePlayer*, bool) = 0; + + virtual bool do_host_migration(CNetGamePlayer* player, short host_token, bool unk) = 0; // aka _0xF8 + + virtual void* leave_from_script() = 0; // calls above function with player = nullptr + + virtual bool _0x108() = 0; + + virtual void* _0x110() = 0; + + virtual bool _0x118() = 0; // related to above function + + CGameScriptHandler* m_script_handler; //0x0008 + char pad_0010[48]; //0x0010 + std::uint32_t m_participants; //0x0040 +}; + static_assert(sizeof(rage::scriptHandler) == 0x60); static_assert(sizeof(CGameScriptHandler) == 0xA0); static_assert(sizeof(CGameScriptHandlerNetwork) == 0xB0); diff --git a/src/hooking.cpp b/src/hooking.cpp index 8933f8e7..53c18aeb 100644 --- a/src/hooking.cpp +++ b/src/hooking.cpp @@ -76,6 +76,9 @@ namespace big detour_hook_helper::add("SSD", g_pointers->m_sort_session_details); + detour_hook_helper::add("APTS", g_pointers->m_add_player_to_session); + detour_hook_helper::add("SCNM", g_pointers->m_send_chat_net_message); + g_hooking = this; } diff --git a/src/hooking.hpp b/src/hooking.hpp index b0bb3f61..6e6e86af 100644 --- a/src/hooking.hpp +++ b/src/hooking.hpp @@ -16,6 +16,8 @@ class CDynamicEntityGameStateDataNode; class CVehicleGadgetDataNode; class CJoinRequestContext; class SessionSortEntry; +class RemoteGamerInfoMsg; +class CMsgTextMessage; namespace rage { @@ -91,6 +93,9 @@ namespace big static bool handle_join_request(Network* network, rage::snSession* session, rage::rlGamerInfo* player_info, CJoinRequestContext* ctx, BOOL is_transition_session); static bool sort_session_details(SessionSortEntry* e1, SessionSortEntry* e2); + + static bool add_player_to_session(rage::netConnectionManager* mgr, int receiver_msg_id, int* out_command_hndl, RemoteGamerInfoMsg* msg, int flags, void* unk); + static bool send_chat_net_message(rage::netConnectionManager* mgr, int receiver_msg_id, CMsgTextMessage* msg, int flags, void* unk); }; class minhook_keepalive diff --git a/src/hooks/info/get_network_event_data.cpp b/src/hooks/info/get_network_event_data.cpp index 7e9184f5..31d74102 100644 --- a/src/hooks/info/get_network_event_data.cpp +++ b/src/hooks/info/get_network_event_data.cpp @@ -1,4 +1,6 @@ #include "hooking.hpp" +#include "gta/net_game_event.hpp" +#include namespace big { diff --git a/src/hooks/misc/send_chat_net_message.cpp b/src/hooks/misc/send_chat_net_message.cpp new file mode 100644 index 00000000..d6ee1405 --- /dev/null +++ b/src/hooks/misc/send_chat_net_message.cpp @@ -0,0 +1,26 @@ +#include "hooking.hpp" +#include "gta_util.hpp" +#include "services/players/player_service.hpp" +#include +#include + +namespace big +{ + bool hooks::send_chat_net_message(rage::netConnectionManager* mgr, int receiver_msg_id, CMsgTextMessage* msg, int flags, void* unk) + { + std::uint64_t host_token = -1; + for (auto& [_, plyr] : g_player_service->players()) + { + if (plyr->get_net_game_player()->m_msg_id == receiver_msg_id) + { + host_token = plyr->get_net_data()->m_host_token; + break; + } + } + + if (g->m_spoofed_peer_ids.contains(host_token)) + msg->m_peer_id = g->m_spoofed_peer_ids[host_token]; + + return g_hooking->get_original()(mgr, receiver_msg_id, msg, flags, unk); + } +} \ No newline at end of file diff --git a/src/hooks/player_management/assign_physical_index.cpp b/src/hooks/player_management/assign_physical_index.cpp index 7af9b1d7..3e581d2b 100644 --- a/src/hooks/player_management/assign_physical_index.cpp +++ b/src/hooks/player_management/assign_physical_index.cpp @@ -11,11 +11,11 @@ namespace big { void* hooks::assign_physical_index(CNetworkPlayerMgr* netPlayerMgr, CNetGamePlayer* player, uint8_t new_index) { - const auto result = g_hooking->get_original()(netPlayerMgr, player, new_index); const auto* net_player_data = player->get_net_data(); if (new_index == static_cast(-1)) { + g->m_spoofed_peer_ids.erase(player->get_net_data()->m_host_token); g_player_service->player_leave(player); if (net_player_data) @@ -29,9 +29,10 @@ namespace big g_notification_service->push("Player Left", std::format("{} freeing slot #{} with Rockstar ID: {}", net_player_data->m_name, player->m_player_id, net_player_data->m_gamer_handle_2.m_rockstar_id)); } - return result; + return g_hooking->get_original()(netPlayerMgr, player, new_index); } + const auto result = g_hooking->get_original()(netPlayerMgr, player, new_index); g_player_service->player_join(player); if (net_player_data) { diff --git a/src/hooks/player_management/network_player_mgr.cpp b/src/hooks/player_management/network_player_mgr.cpp index 2980c64d..51e7dc53 100644 --- a/src/hooks/player_management/network_player_mgr.cpp +++ b/src/hooks/player_management/network_player_mgr.cpp @@ -18,6 +18,7 @@ namespace big void hooks::network_player_mgr_shutdown(CNetworkPlayerMgr* _this) { + g->m_spoofed_peer_ids.clear(); g_player_service->do_cleanup(); if (g->notifications.network_player_mgr_shutdown.log) diff --git a/src/hooks/protections/add_player_to_session.cpp b/src/hooks/protections/add_player_to_session.cpp new file mode 100644 index 00000000..a38c656a --- /dev/null +++ b/src/hooks/protections/add_player_to_session.cpp @@ -0,0 +1,55 @@ +#include "hooking.hpp" +#include "gta_util.hpp" +#include +#include + +// https://stackoverflow.com/questions/8120062/generate-random-64-bit-integer +unsigned +static rand256() +{ + static unsigned const limit = RAND_MAX - RAND_MAX % 256; + unsigned result = rand(); + while (result >= limit) + { + result = rand(); + } + return result % 256; +} + +unsigned long long +static rand64bits() +{ + unsigned long long results = 0ULL; + for (int count = 8; count > 0; --count) + { + results = 256U * results + rand256(); + } + return results; +} + +namespace big +{ + bool hooks::add_player_to_session(rage::netConnectionManager* mgr, int receiver_msg_id, int* out_command_hndl, RemoteGamerInfoMsg* msg, int flags, void* unk) + { + if (msg->m_gamer_info.m_gamer_handle_2.m_rockstar_id == g_local_player->m_player_info->m_net_player_data.m_gamer_handle_2.m_rockstar_id && gta_util::get_network()->m_game_session_ptr->is_host() && g->protections.lessen_breakups) + { + std::uint64_t host_token = -1; + + auto session = gta_util::get_network()->m_game_session_ptr; + for (int i = 0; i < session->m_player_count; i++) + { + if (session->m_players[i]->m_msg_id == receiver_msg_id) + { + host_token = session->m_players[i]->m_player_data.m_host_token; + break; + } + } + + std::uint64_t peer_id = rand64bits(); + g->m_spoofed_peer_ids.emplace(host_token, peer_id); + msg->m_gamer_info.m_peer_id_2 = peer_id; + } + + return g_hooking->get_original()(mgr, receiver_msg_id, out_command_hndl, msg, flags, unk); + } +} \ No newline at end of file diff --git a/src/hooks/protections/receive_net_message.cpp b/src/hooks/protections/receive_net_message.cpp index 93a2f3ea..471ec9e8 100644 --- a/src/hooks/protections/receive_net_message.cpp +++ b/src/hooks/protections/receive_net_message.cpp @@ -3,6 +3,7 @@ #include "natives.hpp" #include "gta_util.hpp" #include "util/session.hpp" +#include "util/spam.hpp" #include namespace big @@ -56,47 +57,39 @@ namespace big switch (msgType) { case rage::eNetMessage::MsgTextMessage: - { - if (g->session.log_chat_messages) - { - char message[256]; - uint64_t unk; - bool is_team; - buffer.ReadString(message, 256); - buffer.ReadQWord(&unk, 64); - buffer.ReadBool(&is_team); - LOG(INFO) << "[CHAT] from " << player->get_name() << ": " << message << (is_team ? " [TEAM]" : " [ALL]"); - } - break; - } case rage::eNetMessage::MsgTextMessage2: { - if (g->session.log_text_messages) + char message[256]; + buffer.ReadString(message, 256); + + if (player->is_spammer) + return true; + + if (spam::is_text_spam(message)) { - char message[256]; - uint64_t unk; - buffer.ReadString(message, 256); - buffer.ReadQWord(&unk, 64); - LOG(INFO) << "[TEXT] from " << player->get_name() << ": " << message; + if (g->session.log_chat_messages) + spam::log_chat(message, player, true); + player->is_spammer = true; + return true; + } + else + { + if (g->session.log_chat_messages) + spam::log_chat(message, player, false); } break; } case rage::eNetMessage::MsgScriptMigrateHost: { - if (std::chrono::system_clock::now() - player->m_last_transition_msg_sent < 200ms) + if (player->m_host_migration_rate_limit.process()) { - if (player->m_num_failed_transition_attempts++ == 20) + if (player->m_host_migration_rate_limit.exceeded_last_process()) { session::add_infraction(player, Infraction::TRIED_KICK_PLAYER); g_notification_service->push_error("Protections", std::format("{} tried to OOM kick you!", player->get_name())); } return true; } - else - { - player->m_last_transition_msg_sent = std::chrono::system_clock::now(); - player->m_num_failed_transition_attempts = 0; - } break; } case rage::eNetMessage::MsgRemoveGamersFromSessionCmd: @@ -181,8 +174,11 @@ namespace big uint32_t num_of_tokens{}; buffer.ReadDword(&num_of_tokens, 32); - if (player && host_token != player->get_net_data()->m_host_token) + if (player && host_token != player->get_net_data()->m_host_token && !player->exposed_desync_protection) + { session::add_infraction(player, Infraction::DESYNC_PROTECTION); + player->exposed_desync_protection = true; + } return true; // block desync kicks as host } diff --git a/src/hooks/protections/received_event.cpp b/src/hooks/protections/received_event.cpp index 10d6128b..2b1902a3 100644 --- a/src/hooks/protections/received_event.cpp +++ b/src/hooks/protections/received_event.cpp @@ -4,6 +4,7 @@ #include #include "gta/script_id.hpp" #include "util/notify.hpp" +#include namespace big { @@ -19,6 +20,121 @@ namespace big id.m_instance_id = buffer.Read(8); } + 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; + + 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; + + if (f208 == 0 && entity && entity->gap28 == 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) + { + g_notification_service->push_error("Warning!", std::format("{} blamed {} for explosion", 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); + } + } + void hooks::received_event( rage::netEventMgr* event_manager, CNetGamePlayer* source_player, @@ -306,6 +422,25 @@ namespace big g->m_syncing_player = source_player; break; } + case eNetworkEvents::NETWORK_PLAY_SOUND_EVENT: + { + auto plyr = g_player_service->get_by_id(source_player->m_player_id); + if (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; + } + break; + } + case eNetworkEvents::EXPLOSION_EVENT: + { + scan_explosion_event(source_player, buffer); + break; + } default: break; } diff --git a/src/hooks/spoofing/send_net_info_to_lobby.cpp b/src/hooks/spoofing/send_net_info_to_lobby.cpp index 6a8d1b25..be7ad051 100644 --- a/src/hooks/spoofing/send_net_info_to_lobby.cpp +++ b/src/hooks/spoofing/send_net_info_to_lobby.cpp @@ -1,5 +1,15 @@ #include "hooking.hpp" +constexpr static auto advertisments = std::to_array( +{ + "~h~~r~YimMenu", + "~h~~g~YimMenu", + "~h~~b~YimMenu", + "~h~~y~YimMenu", + "~h~~o~YimMenu", + "~h~~p~YimMenu" +}); + namespace big { bool hooks::send_net_info_to_lobby(rage::rlGamerInfo* player, int64_t a2, int64_t a3, DWORD* a4) @@ -31,6 +41,20 @@ namespace big if (g->notifications.send_net_info_to_lobby.notify) g_notification_service->push("Player Info Spoofing", "Sent spoofed values to lobby host."); } + else + { + if (g->session.name_spoof_enabled) + { + if (g->session.advertise_menu) + { + memcpy(player->m_name, advertisments[rand() % advertisments.size()], sizeof(player->m_name)); + } + else + { + memcpy(player->m_name, g->session.spoofed_name.c_str(), sizeof(player->m_name)); + } + } + } const auto result = g_hooking->get_original()(player, a2, a3, a4); diff --git a/src/native_hooks/all_scripts.hpp b/src/native_hooks/all_scripts.hpp index 31387a78..c83d4cb6 100644 --- a/src/native_hooks/all_scripts.hpp +++ b/src/native_hooks/all_scripts.hpp @@ -1,6 +1,7 @@ #pragma once #include "native_hooks.hpp" #include "natives.hpp" +#include "core/scr_globals.hpp" namespace big { @@ -16,5 +17,11 @@ namespace big src->set_return_value(return_value); } + + void NETWORK_HAS_RECEIVED_HOST_BROADCAST_DATA(rage::scrNativeCallContext* src) + { + *scr_globals::gsbd.as() = 4; + src->set_return_value(TRUE); + } } } \ No newline at end of file diff --git a/src/native_hooks/am_launcher.hpp b/src/native_hooks/am_launcher.hpp new file mode 100644 index 00000000..d798e828 --- /dev/null +++ b/src/native_hooks/am_launcher.hpp @@ -0,0 +1,44 @@ +#pragma once + +namespace big +{ + namespace am_launcher + { + inline void START_NEW_SCRIPT_WITH_ARGS(rage::scrNativeCallContext* src) + { + const char* name = src->get_arg(0); + uint64_t* args = src->get_arg(1); + int argc = src->get_arg(2); + int stackSize = src->get_arg(3); + + Hash name_hash = rage::joaat(name); + + if (name_hash == RAGE_JOAAT("ggsm_arcade") || + name_hash == RAGE_JOAAT("camhedz_arcade") || + name_hash == RAGE_JOAAT("wizard_arcade") || + name_hash == RAGE_JOAAT("puzzle") || + name_hash == RAGE_JOAAT("fm_intro") || + name_hash == RAGE_JOAAT("pilot_school_mp") || + name_hash == RAGE_JOAAT("golf_mp") || + name_hash == RAGE_JOAAT("tennis_network_mp") || + name_hash == RAGE_JOAAT("fm_race_controler") || + name_hash == RAGE_JOAAT("fm_horde_controler") || + name_hash == RAGE_JOAAT("fm_mission_controller") || + name_hash == RAGE_JOAAT("fm_mission_controller_2020") || + name_hash == RAGE_JOAAT("fm_impromptu_dm_controler") || + name_hash == RAGE_JOAAT("fm_deathmatch_controler") || + name_hash == RAGE_JOAAT("fm_bj_race_controler") || + name_hash == RAGE_JOAAT("fm_survival_controller") || + name_hash == RAGE_JOAAT("tennis_network_mp") || + name_hash == RAGE_JOAAT("sctv") || + name_hash == RAGE_JOAAT("am_pi_menu") + ) + { + src->set_return_value(0); + return; + } + + src->set_return_value(SYSTEM::START_NEW_SCRIPT_WITH_ARGS(name, (Any*)args, argc, stackSize)); + }; + } +} \ No newline at end of file diff --git a/src/native_hooks/freemode.hpp b/src/native_hooks/freemode.hpp index 5bf9bf1b..1161dd5a 100644 --- a/src/native_hooks/freemode.hpp +++ b/src/native_hooks/freemode.hpp @@ -17,5 +17,17 @@ namespace big else src->set_return_value(PLAYER::IS_PLAYER_PLAYING(src->get_arg(0))); }; + + inline void SET_ENTITY_VISIBLE(rage::scrNativeCallContext* src) + { + auto entity = src->get_arg(0); + auto toggle = src->get_arg(1); + auto outfit = src->get_arg(2); + + if (g->self.invisibility && entity == self::ped && toggle) + return; + else + ENTITY::SET_ENTITY_VISIBLE(entity, toggle, outfit); + } } } \ No newline at end of file diff --git a/src/native_hooks/native_hooks.cpp b/src/native_hooks/native_hooks.cpp index 3fb4c118..f4c6bb13 100644 --- a/src/native_hooks/native_hooks.cpp +++ b/src/native_hooks/native_hooks.cpp @@ -5,6 +5,7 @@ #include "gta_util.hpp" #include "shop_controller.hpp" #include "network_session_host.hpp" +#include "am_launcher.hpp" #include