Mission fixes and modder detection improvements (#1598)

* feat(protections): improve protections
* fix: fix mission start
This commit is contained in:
maybegreat48 2023-07-05 07:30:06 +00:00 committed by GitHub
parent 167e1f8d54
commit cbc80e6caf
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
29 changed files with 533 additions and 337 deletions

View File

@ -1,5 +1,6 @@
#include "chat_command_context.hpp" #include "chat_command_context.hpp"
#include "fiber_pool.hpp"
#include "hooking.hpp" #include "hooking.hpp"
#include "util/notify.hpp" #include "util/notify.hpp"

View File

@ -1,6 +1,8 @@
#include "backend/looped/looped.hpp" #include "backend/looped/looped.hpp"
#include "core/scr_globals.hpp" #include "core/scr_globals.hpp"
#include "gta/joaat.hpp" #include "gta/joaat.hpp"
#include "gta/net_array.hpp"
#include "gta_util.hpp"
#include "natives.hpp" #include "natives.hpp"
#include "script_global.hpp" #include "script_global.hpp"
#include "services/players/player_service.hpp" #include "services/players/player_service.hpp"
@ -8,6 +10,7 @@
// Credits: QuickNET // Credits: QuickNET
namespace big namespace big
{ {
static float old_percent = NAN;
constexpr char transition_states[][48] = {"TRANSITION_STATE_EMPTY", "Singleplayer Swoop Up", "Multiplayer Swoop Up", "Creator Swoop Up", "Pre-HUD Checks", "Wait HUD Exit", "Wait For Summon", "Singleplayer Swoop Down", "Multiplayer Swoop Down", "Cancel Joining", "Retry Loading", "Retry Loading Slot 1", "Retry Loading Slot 2", "Retry Loading Slot 3", "Retry Loading Slot 4", "Wait On Invite", "Prejoining Freemode Session Checks", "Look For Fresh Join Freemode", "Look To Join Another Session Freemode", "Confirm Freemode Session Joining", "Wait Join Freemode Session", "Creation Enter Session", "Pre-Freemode Launch Script", "Freemode Teamfull Check", "Start Freemode Launch Script", "Freemode Transition Create Player", "Is Freemode And Transition Ready", "Freemode Swoop Down", "Post Bink Video Warp", "Freemode Final Setup Player", "Move Freemode To Running State", "Freemode How To Terminate", "Start Creator Pre-Launch Script Check", "Start Creator Launch Script", "Creator Transition Create Player", "Is Creator And Transition Ready", "Creator Swoop Down", "Creator Final Setup Player", "Move Creator To Running State", "Prejoining Testbed Session Checks", "Look For Fresh Join Testbed", "Look For Fresh Host Testbed", "Look To Join Another Session Testbed", "Look To Host Session Testbed", "Confirm Testbed Session Joining", "Wait Join Testbed Session", "Start Testbed Launch Script", "Testbed Transition Create Player", "Is Testbed And Transition Ready", "Testbed Swoop Down", "Testbed Final Setup Player", "Move Testbed To Running State", "Testbed How To Terminate", "Quit Current Session Prompt", "Wait For Transition Session To Setup", "Terminate Singleplayer", "Wait Terminate Singleplayer", "Kick Terminate Session", "Terminate Session", "Wait Terminate Session", "Terminate Session And Hold", "Terminate Session And Move Into Holding State", "Team Swapping Checks", "Return To Singleplayer", "Wait For Singleplayer To Start", "Waiting For External Termination Call", "Terminate Maintransition", "Wait For Dirty Load Confirm", "DLC Intro Bink", "Spawn Into Personal Vehicle"}; constexpr char transition_states[][48] = {"TRANSITION_STATE_EMPTY", "Singleplayer Swoop Up", "Multiplayer Swoop Up", "Creator Swoop Up", "Pre-HUD Checks", "Wait HUD Exit", "Wait For Summon", "Singleplayer Swoop Down", "Multiplayer Swoop Down", "Cancel Joining", "Retry Loading", "Retry Loading Slot 1", "Retry Loading Slot 2", "Retry Loading Slot 3", "Retry Loading Slot 4", "Wait On Invite", "Prejoining Freemode Session Checks", "Look For Fresh Join Freemode", "Look To Join Another Session Freemode", "Confirm Freemode Session Joining", "Wait Join Freemode Session", "Creation Enter Session", "Pre-Freemode Launch Script", "Freemode Teamfull Check", "Start Freemode Launch Script", "Freemode Transition Create Player", "Is Freemode And Transition Ready", "Freemode Swoop Down", "Post Bink Video Warp", "Freemode Final Setup Player", "Move Freemode To Running State", "Freemode How To Terminate", "Start Creator Pre-Launch Script Check", "Start Creator Launch Script", "Creator Transition Create Player", "Is Creator And Transition Ready", "Creator Swoop Down", "Creator Final Setup Player", "Move Creator To Running State", "Prejoining Testbed Session Checks", "Look For Fresh Join Testbed", "Look For Fresh Host Testbed", "Look To Join Another Session Testbed", "Look To Host Session Testbed", "Confirm Testbed Session Joining", "Wait Join Testbed Session", "Start Testbed Launch Script", "Testbed Transition Create Player", "Is Testbed And Transition Ready", "Testbed Swoop Down", "Testbed Final Setup Player", "Move Testbed To Running State", "Testbed How To Terminate", "Quit Current Session Prompt", "Wait For Transition Session To Setup", "Terminate Singleplayer", "Wait Terminate Singleplayer", "Kick Terminate Session", "Terminate Session", "Wait Terminate Session", "Terminate Session And Hold", "Terminate Session And Move Into Holding State", "Team Swapping Checks", "Return To Singleplayer", "Wait For Singleplayer To Start", "Waiting For External Termination Call", "Terminate Maintransition", "Wait For Dirty Load Confirm", "DLC Intro Bink", "Spawn Into Personal Vehicle"};
eTransitionState last_state = eTransitionState::TRANSITION_STATE_EMPTY; eTransitionState last_state = eTransitionState::TRANSITION_STATE_EMPTY;
@ -24,24 +27,53 @@ namespace big
SCRIPT::SHUTDOWN_LOADING_SCREEN(); SCRIPT::SHUTDOWN_LOADING_SCREEN();
} }
if (last_state == state || state == eTransitionState::TRANSITION_STATE_EMPTY || state > eTransitionState::TRANSITION_STATE_SPAWN_INTO_PERSONAL_VEHICLE) if ((last_state == state && state != eTransitionState::TRANSITION_STATE_FM_TRANSITION_CREATE_PLAYER) || state == eTransitionState::TRANSITION_STATE_EMPTY || state > eTransitionState::TRANSITION_STATE_SPAWN_INTO_PERSONAL_VEHICLE)
{ {
return; return;
} }
if (HUD::BUSYSPINNER_IS_ON()) if (state != eTransitionState::TRANSITION_STATE_FM_TRANSITION_CREATE_PLAYER && HUD::BUSYSPINNER_IS_ON())
{ {
HUD::BUSYSPINNER_OFF(); HUD::BUSYSPINNER_OFF();
} }
if ((int)state > 0 && (int)state < std::size(transition_states)) if ((int)state > 0 && (int)state < std::size(transition_states))
{
rage::scrThread* freemode{};
if (state == eTransitionState::TRANSITION_STATE_FM_TRANSITION_CREATE_PLAYER
&& (freemode = gta_util::find_script_thread(RAGE_JOAAT("freemode")), freemode && freemode->m_net_component))
{
int num_array_handlers{};
int received_array_handlers{};
while (auto handler = g_pointers->m_gta.m_get_host_array_handler_by_index(freemode->m_net_component, num_array_handlers++))
if (handler->m_flags & 1)
received_array_handlers++;
if (num_array_handlers == 0)
num_array_handlers = 1;
float percent = round((static_cast<float>(received_array_handlers) / num_array_handlers) * 100);
if (percent != old_percent)
{ {
HUD::BEGIN_TEXT_COMMAND_BUSYSPINNER_ON("STRING"); HUD::BEGIN_TEXT_COMMAND_BUSYSPINNER_ON("STRING");
auto const spinner_text = std::format("{} | {}", transition_states[(int)state], static_cast<int>(state)); HUD::ADD_TEXT_COMPONENT_SUBSTRING_PLAYER_NAME(
HUD::ADD_TEXT_COMPONENT_SUBSTRING_PLAYER_NAME(spinner_text.c_str()); std::format("Wait For Host Broadcast Data: {}%", (percent)).c_str());
HUD::END_TEXT_COMMAND_BUSYSPINNER_ON(5); HUD::END_TEXT_COMMAND_BUSYSPINNER_ON(5);
} }
old_percent = percent;
}
else
{
old_percent = NAN;
HUD::BEGIN_TEXT_COMMAND_BUSYSPINNER_ON("STRING");
HUD::ADD_TEXT_COMPONENT_SUBSTRING_PLAYER_NAME(transition_states[(int)state]);
HUD::END_TEXT_COMMAND_BUSYSPINNER_ON(5);
}
}
last_state = state; last_state = state;
} }
} }

View File

@ -36,12 +36,6 @@ namespace big
// perform initial setup // perform initial setup
gta_util::execute_as_script(g.m_dance_thread, [] { gta_util::execute_as_script(g.m_dance_thread, [] {
if (auto hook = g_hooking->m_handler_hooks[(CGameScriptHandler*)rage::scrThread::get()->m_handler].get())
{
hook->disable();
g_hooking->m_handler_hooks.erase((CGameScriptHandler*)rage::scrThread::get()->m_handler);
}
NETWORK::NETWORK_SET_THIS_SCRIPT_IS_NETWORK_SCRIPT(32, true, 32); NETWORK::NETWORK_SET_THIS_SCRIPT_IS_NETWORK_SCRIPT(32, true, 32);
scr_functions::init_nightclub_script({}); scr_functions::init_nightclub_script({});
}); });

View File

@ -70,6 +70,9 @@ namespace big
memory::byte_patch::make(g_pointers->m_gta.m_script_vm_patch_6.add(2).as<uint32_t*>(), 0xd2310272)->apply(); memory::byte_patch::make(g_pointers->m_gta.m_script_vm_patch_6.add(2).as<uint32_t*>(), 0xd2310272)->apply();
memory::byte_patch::make(g_pointers->m_gta.m_script_vm_patch_6.add(6).as<uint16_t*>(), 0x9090)->apply(); memory::byte_patch::make(g_pointers->m_gta.m_script_vm_patch_6.add(6).as<uint16_t*>(), 0x9090)->apply();
// Patch script network check
memory::byte_patch::make(g_pointers->m_gta.m_model_spawn_bypass, std::vector{0x90, 0x90})->apply(); // this is no longer integrity checked
} }
byte_patch_manager::byte_patch_manager() byte_patch_manager::byte_patch_manager()

View File

@ -7,14 +7,19 @@ namespace big
enum class Infraction enum class Infraction
{ {
DESYNC_PROTECTION, DESYNC_PROTECTION,
BREAKUP_KICK_DETECTED, BREAKUP_KICK_DETECTED, // do not use
LOST_CONNECTION_KICK_DETECTED, LOST_CONNECTION_KICK_DETECTED, // do not use
SPOOFED_ROCKSTAR_ID, SPOOFED_ROCKSTAR_ID, // do not use
TRIGGERED_ANTICHEAT, TRIGGERED_ANTICHEAT,
TRIED_CRASH_PLAYER, TRIED_CRASH_PLAYER, // do not use
TRIED_KICK_PLAYER, TRIED_KICK_PLAYER,
BLAME_EXPLOSION_DETECTED, BLAME_EXPLOSION_DETECTED, // do not use (for now)
ATTACKING_WITH_GODMODE ATTACKING_WITH_GODMODE,
ATTACKING_WITH_INVISIBILITY,
ATTACKING_WHEN_HIDDEN_FROM_PLAYER_LIST,
SPOOFED_DATA,
SPOOFED_HOST_TOKEN,
INVALID_PLAYER_MODEL
}; };
inline std::unordered_map<Infraction, const char*> infraction_desc = { inline std::unordered_map<Infraction, const char*> infraction_desc = {
@ -26,6 +31,11 @@ namespace big
{Infraction::TRIED_CRASH_PLAYER, "Tried to crash you"}, {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"}, {Infraction::BLAME_EXPLOSION_DETECTED, "Tried to blame someone for their explosion"},
{Infraction::ATTACKING_WITH_GODMODE, "Attacked someone when using godmode"}, {Infraction::ATTACKING_WITH_GODMODE, "Attacked someone while using godmode"},
{Infraction::ATTACKING_WITH_INVISIBILITY, "Attacked someone while being invisible"},
{Infraction::ATTACKING_WHEN_HIDDEN_FROM_PLAYER_LIST, "Attacked someone while being hidden from the player list"},
{Infraction::SPOOFED_DATA, "Had spoofed data"},
{Infraction::SPOOFED_HOST_TOKEN, "Had spoofed their host token"},
{Infraction::INVALID_PLAYER_MODEL, "Had used an invalid player model"},
}; };
} }

View File

@ -392,7 +392,9 @@ namespace big
bool show_cheating_message = false; bool show_cheating_message = false;
bool anonymous_bounty = true; bool anonymous_bounty = true;
NLOHMANN_DEFINE_TYPE_INTRUSIVE(session, chat_force_clean, log_chat_messages, log_text_messages, decloak_players, force_session_host, force_script_host, player_magnet_enabled, player_magnet_count, is_team, join_in_sctv_slots, kick_chat_spammers, kick_host_when_forcing_host, explosion_karma, damage_karma, disable_traffic, disable_peds, force_thunder, block_ceo_money, randomize_ceo_colors, block_jobs, block_muggers, block_ceo_raids, send_to_apartment_idx, send_to_warehouse_idx, chat_commands, chat_command_default_access_level, show_cheating_message, anonymous_bounty, lock_session) bool fast_join = false;
NLOHMANN_DEFINE_TYPE_INTRUSIVE(session, chat_force_clean, log_chat_messages, log_text_messages, decloak_players, force_session_host, force_script_host, player_magnet_enabled, player_magnet_count, is_team, join_in_sctv_slots, kick_chat_spammers, kick_host_when_forcing_host, explosion_karma, damage_karma, disable_traffic, disable_peds, force_thunder, block_ceo_money, randomize_ceo_colors, block_jobs, block_muggers, block_ceo_raids, send_to_apartment_idx, send_to_warehouse_idx, chat_commands, chat_command_default_access_level, show_cheating_message, anonymous_bounty, lock_session, fast_join)
} session{}; } session{};
struct settings struct settings

View File

@ -6,6 +6,7 @@ class NetworkGameFilterMatchmakingComponent;
class sCloudFile; class sCloudFile;
class CPlayerGameStateDataNode; class CPlayerGameStateDataNode;
class CVehicleGadgetDataNode; class CVehicleGadgetDataNode;
class CGameScriptHandlerNetComponent;
enum eVehicleGadgetType : uint32_t; enum eVehicleGadgetType : uint32_t;
namespace rage namespace rage
@ -22,6 +23,7 @@ namespace rage
class rlScHandle; class rlScHandle;
class rlQueryPresenceAttributesContext; class rlQueryPresenceAttributesContext;
enum class eThreadState : uint32_t; enum class eThreadState : uint32_t;
class netArrayHandlerBase;
} }
namespace datafile_commands namespace datafile_commands
@ -141,4 +143,6 @@ namespace big::functions
using handle_chat_message = void (*)(void* chat_data, void*, rage::rlGamerHandle* handle, const char* text, bool is_team); using handle_chat_message = void (*)(void* chat_data, void*, rage::rlGamerHandle* handle, const char* text, bool is_team);
using update_language = void (*)(bool); using update_language = void (*)(bool);
using get_host_array_handler_by_index = rage::netArrayHandlerBase* (*)(CGameScriptHandlerNetComponent* component, int index);
} }

View File

@ -65,6 +65,7 @@ namespace rage
// ... // ...
}; };
#pragma pack(push, 1)
class netArrayHandlerBase class netArrayHandlerBase
{ {
public: public:
@ -191,7 +192,7 @@ namespace rage
virtual void _0x1E0() = 0; virtual void _0x1E0() = 0;
virtual void _0x1E8(bool) = 0;// very important! changes send function to use some kind of cached buffer that prevents us from modifing array data per player virtual void _0x1E8(bool) = 0;
void* m_something; // 0x10 void* m_something; // 0x10
@ -207,27 +208,9 @@ namespace rage
uint8_t m_element_size_2; // 250 uint8_t m_element_size_2; // 250
uint8_t m_pad3[13]; // 251 uint8_t m_pad3[13]; // 251
void* m_array; // 264 void* m_array; // 264
uint8_t m_pad4[341 - (264 + 8)];
#if 0 char m_flags; // 341
static inline netArrayHandlerBase* get_by_data(void* data)
{
if (auto array_mgr = *big::g_pointers->m_gta.m_game_array_mgr)
{
if (auto handler = array_mgr->m_start)
{
do
{
if (handler->m_array == data)
return handler;
}
while (handler = handler->m_next);
}
}
return nullptr;
}
#endif
}; };
#pragma pack(pop)
static_assert(sizeof(netArrayHandlerBase) == 272); static_assert(sizeof(netArrayHandlerBase) == 342);
} }

View File

@ -203,8 +203,6 @@ namespace big
PVOID m_serialize_take_off_ped_variation_task; PVOID m_serialize_take_off_ped_variation_task;
PVOID m_create_script_handler;
functions::encode_session_info m_encode_session_info; functions::encode_session_info m_encode_session_info;
functions::decode_session_info m_decode_session_info; functions::decode_session_info m_decode_session_info;
functions::decode_peer_info m_decode_peer_info; functions::decode_peer_info m_decode_peer_info;
@ -263,6 +261,10 @@ namespace big
int* m_language; int* m_language;
functions::update_language m_update_language{}; functions::update_language m_update_language{};
PVOID m_model_spawn_bypass{};
functions::get_host_array_handler_by_index m_get_host_array_handler_by_index;
}; };
#pragma pack(pop) #pragma pack(pop)
static_assert(sizeof(gta_pointers) % 8 == 0, "Pointers are not properly aligned"); static_assert(sizeof(gta_pointers) % 8 == 0, "Pointers are not properly aligned");

View File

@ -84,8 +84,6 @@ namespace big
detour_hook_helper::add<hooks::serialize_take_off_ped_variation_task>("STOPVT", g_pointers->m_gta.m_serialize_take_off_ped_variation_task); detour_hook_helper::add<hooks::serialize_take_off_ped_variation_task>("STOPVT", g_pointers->m_gta.m_serialize_take_off_ped_variation_task);
detour_hook_helper::add<hooks::create_script_handler>("CSH", g_pointers->m_gta.m_create_script_handler);
detour_hook_helper::add<hooks::queue_dependency>("QD", g_pointers->m_gta.m_queue_dependency); detour_hook_helper::add<hooks::queue_dependency>("QD", g_pointers->m_gta.m_queue_dependency);
detour_hook_helper::add<hooks::prepare_metric_for_sending>("PMFS", g_pointers->m_gta.m_prepare_metric_for_sending); detour_hook_helper::add<hooks::prepare_metric_for_sending>("PMFS", g_pointers->m_gta.m_prepare_metric_for_sending);
@ -141,12 +139,6 @@ namespace big
detour_hook_helper->m_detour_hook->enable(); detour_hook_helper->m_detour_hook->enable();
} }
for (auto& thread : *g_pointers->m_gta.m_script_threads)
{
if (thread->m_handler)
hook_script_handler((CGameScriptHandler*)thread->m_handler);
}
MH_ApplyQueued(); MH_ApplyQueued();
m_enabled = true; m_enabled = true;
@ -171,7 +163,6 @@ namespace big
delete detour_hook_helper; delete detour_hook_helper;
} }
m_detour_hook_helpers.clear(); m_detour_hook_helpers.clear();
m_handler_hooks.clear();
} }
hooking::detour_hook_helper::~detour_hook_helper() hooking::detour_hook_helper::~detour_hook_helper()
@ -195,8 +186,6 @@ namespace big
bool hooks::run_script_threads(std::uint32_t ops_to_execute) bool hooks::run_script_threads(std::uint32_t ops_to_execute)
{ {
g_native_invoker.cache_handlers();
if (g_running) if (g_running)
{ {
g_script_mgr.tick(); g_script_mgr.tick();

View File

@ -123,10 +123,6 @@ namespace big
static void serialize_take_off_ped_variation_task(ClonedTakeOffPedVariationInfo* info, rage::CSyncDataBase* serializer); static void serialize_take_off_ped_variation_task(ClonedTakeOffPedVariationInfo* info, rage::CSyncDataBase* serializer);
static CGameScriptHandler* create_script_handler(CGameScriptHandlerMgr* this_, void* unk);
static bool script_handler_is_networked(CGameScriptHandler* this_);
static bool script_handler_dtor(CGameScriptHandler* this_, bool free_memory);
static int nt_query_virtual_memory(void* _this, HANDLE handle, PVOID base_addr, int info_class, MEMORY_BASIC_INFORMATION* info, int size, size_t* return_len); static int nt_query_virtual_memory(void* _this, HANDLE handle, PVOID base_addr, int info_class, MEMORY_BASIC_INFORMATION* info, int size, size_t* return_len);
static void queue_dependency(void* dependency); static void queue_dependency(void* dependency);
static void prepare_metric_for_sending(rage::datBitBuffer* bit_buffer, int unk, int time, rage::rlMetric* metric); static void prepare_metric_for_sending(rage::datBitBuffer* bit_buffer, int unk, int time, rage::rlMetric* metric);
@ -241,9 +237,6 @@ namespace big
return detour_hook_helper::hook_to_detour_hook_helper<detour_function>::m_detour_hook->get_original<decltype(detour_function)>(); return detour_hook_helper::hook_to_detour_hook_helper<detour_function>::m_detour_hook->get_original<decltype(detour_function)>();
} }
void hook_script_handler(CGameScriptHandler* handler);
std::unordered_map<CGameScriptHandler*, std::unique_ptr<vmt_hook>> m_handler_hooks;
private: private:
bool m_enabled{}; bool m_enabled{};
minhook_keepalive m_minhook_keepalive; minhook_keepalive m_minhook_keepalive;

View File

@ -1,12 +1,61 @@
#include "gta/net_game_event.hpp" #include "gta/net_game_event.hpp"
#include "hooking.hpp" #include "hooking.hpp"
#include "services/players/player_service.hpp" #include "services/players/player_service.hpp"
#include "util/globals.hpp"
#include "util/misc.hpp"
#include "util/session.hpp" #include "util/session.hpp"
#include <entities/CDynamicEntity.hpp> #include <entities/CDynamicEntity.hpp>
#include <script/globals/GPBD_FM.hpp>
#include <script/globals/GlobalPlayerBD.hpp>
namespace big namespace big
{ {
inline bool is_invincible(big::player_ptr player)
{
return player->get_ped() && (player->get_ped()->m_damage_bits & (1 << 8));
}
inline bool is_invisible(big::player_ptr player)
{
if (!player->get_ped())
return false;
if (!NETWORK::NETWORK_ARE_PLAYERS_IN_SAME_TUTORIAL_SESSION(self::id, player->id()))
return false; // probably not
if (scr_globals::globalplayer_bd.as<GlobalPlayerBD*>()->Entries[player->id()].IsInvisible)
return true;
if ((player->get_current_vehicle() && player->get_current_vehicle()->m_driver == player->get_ped())
|| PLAYER::IS_REMOTE_PLAYER_IN_NON_CLONED_VEHICLE(player->id()))
return false; // can't say
return false; // TODO! have to get data from CPhysicalGameStateDataNode
//return (player->get_ped()->m_flags & (int)rage::fwEntity::EntityFlags::IS_VISIBLE) == 0;
}
inline bool is_hidden_from_player_list(big::player_ptr player)
{
return scr_globals::globalplayer_bd.as<GlobalPlayerBD*>()->Entries[player->id()].CayoPericoFlags & 1;
}
inline bool is_using_rc_vehicle(big::player_ptr player)
{
if (misc::has_bit_set(&scr_globals::gpbd_fm_1.as<GPBD_FM*>()->Entries[player->id()].PropertyData.PAD_0365, 29))
return true; // bandito
if (misc::has_bit_set(&scr_globals::gpbd_fm_1.as<GPBD_FM*>()->Entries[player->id()].PropertyData.ArcadeData.AppearanceBitset2, 16))
return true; // tank
return false;
}
inline bool is_using_orbital_cannon(big::player_ptr player)
{
return scr_globals::globalplayer_bd.as<GlobalPlayerBD*>()->Entries[player->id()].OrbitalBitset.IsSet(eOrbitalBitset::kOrbitalCannonActive);
}
void hooks::get_network_event_data(int64_t unk, rage::CEventNetwork* net_event) void hooks::get_network_event_data(int64_t unk, rage::CEventNetwork* net_event)
{ {
switch (net_event->get_type()) switch (net_event->get_type())
@ -21,7 +70,9 @@ namespace big
rage::sEntityDamagedData damage_data; rage::sEntityDamagedData damage_data;
net_event->get_extra_information(&damage_data, sizeof(damage_data)); net_event->get_extra_information(&damage_data, sizeof(damage_data));
if (damage_data.m_weapon_used == RAGE_JOAAT("weapon_explosion")) if (damage_data.m_weapon_used == RAGE_JOAAT("WEAPON_STICKYBOMB") || damage_data.m_weapon_used == RAGE_JOAAT("VEHICLE_WEAPON_MINE_KINETIC_RC")
|| damage_data.m_weapon_used == RAGE_JOAAT("VEHICLE_WEAPON_MINE_EMP_RC") || damage_data.m_weapon_used == RAGE_JOAAT("VEHICLE_WEAPON_MINE_KINETIC")
|| damage_data.m_weapon_used == RAGE_JOAAT("VEHICLE_WEAPON_MINE_EMP") || damage_data.m_weapon_used == RAGE_JOAAT("VEHICLE_WEAPON_MINE_SPIKE"))
break; break;
if (auto damager = g_pointers->m_gta.m_handle_to_ptr(damage_data.m_damager_index); if (auto damager = g_pointers->m_gta.m_handle_to_ptr(damage_data.m_damager_index);
@ -30,13 +81,60 @@ namespace big
if (auto player = g_player_service->get_by_host_token( if (auto player = g_player_service->get_by_host_token(
reinterpret_cast<CPed*>(damager)->m_player_info->m_net_player_data.m_host_token)) reinterpret_cast<CPed*>(damager)->m_player_info->m_net_player_data.m_host_token))
{ {
if (auto victim = g_pointers->m_gta.m_handle_to_ptr(damage_data.m_victim_index); if (PLAYER::IS_REMOTE_PLAYER_IN_NON_CLONED_VEHICLE(player->id()))
victim && victim->m_entity_type == 4 && reinterpret_cast<CPed*>(victim)->m_player_info)
{ {
if (reinterpret_cast<CPed*>(damager)->m_damage_bits & (1 << 8)) if (scr_globals::globalplayer_bd.as<GlobalPlayerBD*>()->Entries[player->id()].PlayerBlip.PlayerVehicleBlipType == eBlipType::SUBMARINE)
break;
if (is_using_rc_vehicle(player))
break;
}
else
{
if (auto vehicle = player->get_current_vehicle())
if (auto model_info = vehicle->m_model_info)
if (model_info->m_hash == RAGE_JOAAT("rcbandito") || model_info->m_hash == RAGE_JOAAT("minitank")
|| model_info->m_hash == RAGE_JOAAT("kosatka"))
break;
}
if (NETWORK::NETWORK_IS_ACTIVITY_SESSION())
break;
if (globals::get_interior_from_player(player->id()) != 0)
break;
if (player->get_player_info() && player->get_player_info()->m_game_state == eGameState::InMPCutscene)
break;
if (auto victim = g_pointers->m_gta.m_handle_to_ptr(damage_data.m_victim_index); victim && victim->m_entity_type == 4)
{
if (is_invincible(player))
{ {
session::add_infraction(player, Infraction::ATTACKING_WITH_GODMODE); session::add_infraction(player, Infraction::ATTACKING_WITH_GODMODE);
} }
if (is_invisible(player))
{
if (!reinterpret_cast<CPed*>(victim)->m_player_info)
break;
if (damage_data.m_weapon_used == RAGE_JOAAT("WEAPON_EXPLOSION") || damage_data.m_weapon_used == RAGE_JOAAT("WEAPON_RAMMED_BY_CAR")
|| damage_data.m_weapon_used == RAGE_JOAAT("WEAPON_RUN_OVER_BY_CAR"))
break;
session::add_infraction(player, Infraction::ATTACKING_WITH_INVISIBILITY);
}
if (is_hidden_from_player_list(player))
{
session::add_infraction(player, Infraction::ATTACKING_WHEN_HIDDEN_FROM_PLAYER_LIST);
}
if (is_using_orbital_cannon(player))
{
session::add_infraction(player, Infraction::SPOOFED_DATA);
}
} }
} }
} }

View File

@ -8,12 +8,20 @@
#include "services/player_database/player_database_service.hpp" #include "services/player_database/player_database_service.hpp"
#include "services/players/player_service.hpp" #include "services/players/player_service.hpp"
#include "util/notify.hpp" #include "util/notify.hpp"
#include "util/session.hpp"
#include <network/Network.hpp> #include <network/Network.hpp>
namespace big namespace big
{ {
inline bool is_spoofed_host_token(std::uint64_t token)
{
if (token < 200'000'000)
return true;
return false;
}
void* hooks::assign_physical_index(CNetworkPlayerMgr* netPlayerMgr, CNetGamePlayer* player, uint8_t new_index) void* hooks::assign_physical_index(CNetworkPlayerMgr* netPlayerMgr, CNetGamePlayer* player, uint8_t new_index)
{ {
@ -83,9 +91,8 @@ namespace big
} }
auto id = player->m_player_id; auto id = player->m_player_id;
bool lock_session = g.session.lock_session;
g_fiber_pool->queue_job([id, lock_session] { g_fiber_pool->queue_job([id] {
if (auto plyr = g_player_service->get_by_id(id)) if (auto plyr = g_player_service->get_by_id(id))
{ {
if (plyr->get_net_data()->m_gamer_handle.m_rockstar_id != 0) if (plyr->get_net_data()->m_gamer_handle.m_rockstar_id != 0)
@ -106,32 +113,30 @@ namespace big
} }
} }
} }
if (plyr->block_join) if (plyr->block_join)
{ {
if (g_player_service->get_self()->is_host()) if (g_player_service->get_self()->is_host())
{ {
dynamic_cast<player_command*>(command::get(RAGE_JOAAT("breakup")))->call(plyr, {}); dynamic_cast<player_command*>(command::get(RAGE_JOAAT("breakup")))->call(plyr, {});
g_notification_service->push_warning("Block Join",
std::format("Block Join method failed for {}, sending breakup kick instead...",
plyr->get_net_data()->m_name));
LOG(WARNING) << "Sending Breakup Kick due to block join failure... ";
} }
else else
{ {
g_notification_service->push_warning("Block Join",
std::format("Block Join method failed for {}, can't send breakup without host...\n trying Desync",
plyr->get_net_data()->m_name));
LOG(WARNING) << "Failed blocking join due to not being host... trying Desync ";
dynamic_cast<player_command*>(command::get(RAGE_JOAAT("desync")))->call(plyr, {}); dynamic_cast<player_command*>(command::get(RAGE_JOAAT("desync")))->call(plyr, {});
} }
} }
if (lock_session && g_player_service->get_self()->is_host())
if (g.session.lock_session && g_player_service->get_self()->is_host())
{ {
dynamic_cast<player_command*>(command::get(RAGE_JOAAT("breakup")))->call(plyr, {}); dynamic_cast<player_command*>(command::get(RAGE_JOAAT("breakup")))->call(plyr, {});
g_notification_service->push_warning("Lock Session", g_notification_service->push_warning("Lock Session",
std::format("A player with the name of {} has been denied entry", plyr->get_net_data()->m_name)); std::format("A player with the name of {} has been denied entry", plyr->get_net_data()->m_name));
} }
if (is_spoofed_host_token(plyr->get_net_data()->m_host_token))
{
session::add_infraction(plyr, Infraction::SPOOFED_HOST_TOKEN);
}
} }
}); });
} }

View File

@ -16,6 +16,7 @@
#include "netsync/nodes/player/CPlayerAppearanceDataNode.hpp" #include "netsync/nodes/player/CPlayerAppearanceDataNode.hpp"
#include "netsync/nodes/player/CPlayerCreationDataNode.hpp" #include "netsync/nodes/player/CPlayerCreationDataNode.hpp"
#include "netsync/nodes/player/CPlayerGameStateDataNode.hpp" #include "netsync/nodes/player/CPlayerGameStateDataNode.hpp"
#include "netsync/nodes/player/CPlayerGamerDataNode.hpp"
#include "netsync/nodes/proximity_migrateable/CSectorDataNode.hpp" #include "netsync/nodes/proximity_migrateable/CSectorDataNode.hpp"
#include "netsync/nodes/train/CTrainGameStateDataNode.hpp" #include "netsync/nodes/train/CTrainGameStateDataNode.hpp"
#include "netsync/nodes/vehicle/CVehicleCreationDataNode.hpp" #include "netsync/nodes/vehicle/CVehicleCreationDataNode.hpp"
@ -25,6 +26,7 @@
#include "network/netObject.hpp" #include "network/netObject.hpp"
#include "util/model_info.hpp" #include "util/model_info.hpp"
#include "util/notify.hpp" #include "util/notify.hpp"
#include "util/session.hpp"
#include "vehicle/CVehicleModelInfo.hpp" #include "vehicle/CVehicleModelInfo.hpp"
namespace big namespace big
@ -547,10 +549,45 @@ namespace big
constexpr uint32_t crash_objects[] = {RAGE_JOAAT("prop_dummy_01"), RAGE_JOAAT("prop_dummy_car"), RAGE_JOAAT("prop_dummy_light"), RAGE_JOAAT("prop_dummy_plane"), RAGE_JOAAT("prop_distantcar_night"), RAGE_JOAAT("prop_distantcar_day"), RAGE_JOAAT("hei_bh1_08_details4_em_night"), RAGE_JOAAT("dt1_18_sq_night_slod"), RAGE_JOAAT("ss1_12_night_slod"), -1288391198, RAGE_JOAAT("h4_prop_bush_bgnvla_med_01"), RAGE_JOAAT("h4_prop_bush_bgnvla_lrg_01"), RAGE_JOAAT("h4_prop_bush_buddleia_low_01"), RAGE_JOAAT("h4_prop_bush_ear_aa"), RAGE_JOAAT("h4_prop_bush_ear_ab"), RAGE_JOAAT("h4_prop_bush_fern_low_01"), RAGE_JOAAT("h4_prop_bush_fern_tall_cc"), RAGE_JOAAT("h4_prop_bush_mang_ad"), RAGE_JOAAT("h4_prop_bush_mang_low_aa"), RAGE_JOAAT("h4_prop_bush_mang_low_ab"), RAGE_JOAAT("h4_prop_bush_seagrape_low_01"), RAGE_JOAAT("prop_h4_ground_cover"), RAGE_JOAAT("h4_prop_weed_groundcover_01"), RAGE_JOAAT("h4_prop_grass_med_01"), RAGE_JOAAT("h4_prop_grass_tropical_lush_01"), RAGE_JOAAT("h4_prop_grass_wiregrass_01"), RAGE_JOAAT("h4_prop_weed_01_plant"), RAGE_JOAAT("h4_prop_weed_01_row"), RAGE_JOAAT("urbanweeds02_l1"), RAGE_JOAAT("proc_forest_grass01"), RAGE_JOAAT("prop_small_bushyba"), RAGE_JOAAT("v_res_d_dildo_a"), RAGE_JOAAT("v_res_d_dildo_b"), RAGE_JOAAT("v_res_d_dildo_c"), RAGE_JOAAT("v_res_d_dildo_d"), RAGE_JOAAT("v_res_d_dildo_e"), RAGE_JOAAT("v_res_d_dildo_f"), RAGE_JOAAT("v_res_skateboard"), RAGE_JOAAT("prop_battery_01"), RAGE_JOAAT("prop_barbell_01"), RAGE_JOAAT("prop_barbell_02"), RAGE_JOAAT("prop_bandsaw_01"), RAGE_JOAAT("prop_bbq_3"), RAGE_JOAAT("v_med_curtainsnewcloth2"), RAGE_JOAAT("bh1_07_flagpoles"), 92962485}; constexpr uint32_t crash_objects[] = {RAGE_JOAAT("prop_dummy_01"), RAGE_JOAAT("prop_dummy_car"), RAGE_JOAAT("prop_dummy_light"), RAGE_JOAAT("prop_dummy_plane"), RAGE_JOAAT("prop_distantcar_night"), RAGE_JOAAT("prop_distantcar_day"), RAGE_JOAAT("hei_bh1_08_details4_em_night"), RAGE_JOAAT("dt1_18_sq_night_slod"), RAGE_JOAAT("ss1_12_night_slod"), -1288391198, RAGE_JOAAT("h4_prop_bush_bgnvla_med_01"), RAGE_JOAAT("h4_prop_bush_bgnvla_lrg_01"), RAGE_JOAAT("h4_prop_bush_buddleia_low_01"), RAGE_JOAAT("h4_prop_bush_ear_aa"), RAGE_JOAAT("h4_prop_bush_ear_ab"), RAGE_JOAAT("h4_prop_bush_fern_low_01"), RAGE_JOAAT("h4_prop_bush_fern_tall_cc"), RAGE_JOAAT("h4_prop_bush_mang_ad"), RAGE_JOAAT("h4_prop_bush_mang_low_aa"), RAGE_JOAAT("h4_prop_bush_mang_low_ab"), RAGE_JOAAT("h4_prop_bush_seagrape_low_01"), RAGE_JOAAT("prop_h4_ground_cover"), RAGE_JOAAT("h4_prop_weed_groundcover_01"), RAGE_JOAAT("h4_prop_grass_med_01"), RAGE_JOAAT("h4_prop_grass_tropical_lush_01"), RAGE_JOAAT("h4_prop_grass_wiregrass_01"), RAGE_JOAAT("h4_prop_weed_01_plant"), RAGE_JOAAT("h4_prop_weed_01_row"), RAGE_JOAAT("urbanweeds02_l1"), RAGE_JOAAT("proc_forest_grass01"), RAGE_JOAAT("prop_small_bushyba"), RAGE_JOAAT("v_res_d_dildo_a"), RAGE_JOAAT("v_res_d_dildo_b"), RAGE_JOAAT("v_res_d_dildo_c"), RAGE_JOAAT("v_res_d_dildo_d"), RAGE_JOAAT("v_res_d_dildo_e"), RAGE_JOAAT("v_res_d_dildo_f"), RAGE_JOAAT("v_res_skateboard"), RAGE_JOAAT("prop_battery_01"), RAGE_JOAAT("prop_barbell_01"), RAGE_JOAAT("prop_barbell_02"), RAGE_JOAAT("prop_bandsaw_01"), RAGE_JOAAT("prop_bbq_3"), RAGE_JOAAT("v_med_curtainsnewcloth2"), RAGE_JOAAT("bh1_07_flagpoles"), 92962485};
inline CObject* get_game_object(rage::netObject* object) constexpr uint32_t valid_player_models[] = {
{ RAGE_JOAAT("mp_m_freemode_01"),
return *(CObject**)((__int64)object + 0x50); RAGE_JOAAT("mp_f_freemode_01"),
} RAGE_JOAAT("u_m_m_filmdirector"),
RAGE_JOAAT("player_zero"),
RAGE_JOAAT("player_one"),
RAGE_JOAAT("player_two"),
// peyote
RAGE_JOAAT("A_C_Boar"),
RAGE_JOAAT("A_C_Cat_01"),
RAGE_JOAAT("A_C_Cow"),
RAGE_JOAAT("A_C_Coyote"),
RAGE_JOAAT("A_C_Deer"),
RAGE_JOAAT("A_C_Husky"),
RAGE_JOAAT("A_C_MtLion"),
RAGE_JOAAT("A_C_Pig"),
RAGE_JOAAT("A_C_Poodle"),
RAGE_JOAAT("A_C_Pug"),
RAGE_JOAAT("A_C_Rabbit_01"),
RAGE_JOAAT("A_C_Retriever"),
RAGE_JOAAT("A_C_Rottweiler"),
RAGE_JOAAT("A_C_shepherd"),
RAGE_JOAAT("A_C_Westy"),
RAGE_JOAAT("A_C_Chickenhawk"),
RAGE_JOAAT("A_C_Cormorant"),
RAGE_JOAAT("A_C_Crow"),
RAGE_JOAAT("A_C_Hen"),
RAGE_JOAAT("A_C_Pigeon"),
RAGE_JOAAT("A_C_Seagull"),
RAGE_JOAAT("A_C_Dolphin"),
RAGE_JOAAT("A_C_Fish"),
RAGE_JOAAT("A_C_KillerWhale"),
RAGE_JOAAT("A_C_SharkHammer"),
RAGE_JOAAT("A_C_SharkTiger"),
RAGE_JOAAT("A_C_Stingray"),
RAGE_JOAAT("IG_Orleans"),
RAGE_JOAAT("A_C_Chop"),
RAGE_JOAAT("A_C_HumpBack"),
};
inline bool is_crash_ped(uint32_t model) inline bool is_crash_ped(uint32_t model)
{ {
@ -566,9 +603,11 @@ namespace big
{ {
if (!model_info::is_model_of_type(model, eModelType::Vehicle, eModelType::Unk133)) if (!model_info::is_model_of_type(model, eModelType::Vehicle, eModelType::Unk133))
return true; return true;
for (auto iterator : crash_vehicles) for (auto iterator : crash_vehicles)
if (iterator == model) if (iterator == model)
return true; return true;
return false; return false;
} }
@ -576,28 +615,81 @@ namespace big
{ {
if (!model_info::get_model(model)) if (!model_info::get_model(model))
return false; return false;
if (!model_info::is_model_of_type(model, eModelType::Object, eModelType::Time, eModelType::Weapon, eModelType::Destructable, eModelType::WorldObject, eModelType::Sprinkler, eModelType::Unk65, eModelType::Plant, eModelType::LOD, eModelType::Unk132, eModelType::Building)) if (!model_info::is_model_of_type(model, eModelType::Object, eModelType::Time, eModelType::Weapon, eModelType::Destructable, eModelType::WorldObject, eModelType::Sprinkler, eModelType::Unk65, eModelType::Plant, eModelType::LOD, eModelType::Unk132, eModelType::Building))
return true; return true;
for (auto iterator : crash_objects) for (auto iterator : crash_objects)
if (iterator == model) if (iterator == model)
return true; return true;
return false; return false;
} }
inline bool is_attachment_infinite(rage::CDynamicEntity* object, uint16_t attached_to_net_id) inline bool is_valid_player_model(uint32_t model)
{
for (auto iterator : valid_player_models)
if (iterator == model)
return true;
return false;
}
inline void check_player_model(player_ptr player, uint32_t model)
{
if (!player)
return;
if (NETWORK::NETWORK_IS_ACTIVITY_SESSION())
return;
if (!is_valid_player_model(model))
{
session::add_infraction(player, Infraction::INVALID_PLAYER_MODEL);
}
}
// the game function does weird stuff that we don't want
inline CObject* get_entity_attached_to(CObject* entity)
{
if (!entity)
return nullptr;
if (!entity->gap50)
return nullptr;
__int64 component = *(__int64*)((__int64)(entity->gap50) + 0x48);
if (!component)
return nullptr;
int unk_count = *(int*)(component + 0x5C) & 0xF;
if (unk_count < 2)
return nullptr;
return *(CObject**)(component);
}
inline bool is_attachment_infinite(rage::netObject* object, uint16_t attached_to_net_id, int from_bone, int to_bone)
{ {
if (object == nullptr) if (object == nullptr)
return false; return false;
constexpr size_t reasonable_limit = 150; auto target = g_pointers->m_gta.m_get_net_object(*g_pointers->m_gta.m_network_object_mgr, attached_to_net_id, false);
size_t i = 0;
while (object && i < reasonable_limit) while (target)
{ {
if (object->m_net_object && object->m_net_object->m_object_id == attached_to_net_id) if (target == object)
return true; return true;
object = g_pointers->m_gta.m_get_entity_attached_to(object); auto next = get_entity_attached_to(target->GetGameObject());
i++;
if (!next)
return false;
if (!next->m_net_object)
return false;
target = next->m_net_object;
} }
return false; return false;
@ -629,6 +721,26 @@ namespace big
return false; return false;
} }
inline bool is_sane_override_pos(float x, float y, float z)
{
if (isnan(x) || isnan(y) || isnan(z))
return false;
if (isinf(x) || isinf(y) || isinf(z))
return false;
if (x > 5000.0f || x < -5000.0f)
return false;
if (y > 8500.0f || y < -5000.0f)
return false;
if (z > 1600.0f || z < -700.0f)
return false;
return true;
}
bool check_node(rage::netSyncNodeBase* node, CNetGamePlayer* sender, rage::netObject* object) bool check_node(rage::netSyncNodeBase* node, CNetGamePlayer* sender, rage::netObject* object)
{ {
if (node->IsParentNode()) if (node->IsParentNode())
@ -642,9 +754,13 @@ namespace big
else if (node->IsDataNode()) else if (node->IsDataNode())
{ {
const auto vft = *(uintptr_t*)node; const auto vft = *(uintptr_t*)node;
auto sender_plyr = g_player_service->get_by_id(sender->m_player_id);
for (const sync_node_id node_id : sync_node_finder::find((eNetObjType)object->m_object_type, vft)) for (const sync_node_id node_id : sync_node_finder::find((eNetObjType)object->m_object_type, vft))
{ {
if ((((CProjectBaseSyncDataNode*)node)->flags & 1) == 0)
continue;
switch (node_id) switch (node_id)
{ {
case sync_node_id("CVehicleCreationDataNode"): case sync_node_id("CVehicleCreationDataNode"):
@ -681,17 +797,13 @@ namespace big
{ {
const auto attach_node = (CPhysicalAttachDataNode*)(node); const auto attach_node = (CPhysicalAttachDataNode*)(node);
// TODO: Find a better method to avoid false positives if (attach_node->m_attached
auto model_hash = get_game_object(object) ? get_game_object(object)->m_model_info->m_hash : 0; && is_attachment_infinite(object,
if (attach_node->m_attached && attach_node->m_attached_to == object->m_object_id && (model_hash != RAGE_JOAAT("hauler2") && model_hash != RAGE_JOAAT("phantom3"))) attach_node->m_attached_to,
attach_node->m_attach_bone,
attach_node->m_other_attach_bone))
{ {
// notify::crash_blocked(sender, "infinite physical attachment"); notify::crash_blocked(sender, "infinite physical attachment");
return true;
}
else if (attach_node->m_attached
&& is_attachment_infinite((rage::CDynamicEntity*)get_game_object(object), attach_node->m_attached_to))
{
// notify::crash_blocked(sender, "recursive infinite physical attachment");
return true; return true;
} }
@ -715,16 +827,15 @@ namespace big
case sync_node_id("CPedAttachDataNode"): case sync_node_id("CPedAttachDataNode"):
{ {
const auto attach_node = (CPedAttachDataNode*)(node); const auto attach_node = (CPedAttachDataNode*)(node);
if (attach_node->m_attached && attach_node->m_attached_to == object->m_object_id) if (attach_node->m_attached
&& is_attachment_infinite(object,
attach_node->m_attached_to,
attach_node->m_attachment_bone,
attach_node->m_attachment_bone))
{ {
notify::crash_blocked(sender, "infinite ped attachment"); notify::crash_blocked(sender, "infinite ped attachment");
return true; return true;
} }
else if (attach_node->m_attached && is_attachment_infinite(get_game_object(object), attach_node->m_attached_to))
{
// notify::crash_blocked(sender, "recursive infinite ped attachment");
return true;
}
break; break;
} }
@ -746,6 +857,7 @@ namespace big
notify::crash_blocked(sender, "invalid player model (appearance node)"); notify::crash_blocked(sender, "invalid player model (appearance node)");
return true; return true;
} }
check_player_model(sender_plyr, player_appearance_node->m_model_hash);
break; break;
} }
case sync_node_id("CPlayerCreationDataNode"): case sync_node_id("CPlayerCreationDataNode"):
@ -756,6 +868,7 @@ namespace big
notify::crash_blocked(sender, "invalid player model (creation node)"); notify::crash_blocked(sender, "invalid player model (creation node)");
return true; return true;
} }
check_player_model(sender_plyr, player_creation_node->m_model);
break; break;
} }
case sync_node_id("CSectorDataNode"): case sync_node_id("CSectorDataNode"):
@ -771,8 +884,10 @@ namespace big
case sync_node_id("CPlayerGameStateDataNode"): case sync_node_id("CPlayerGameStateDataNode"):
{ {
const auto game_state_node = (CPlayerGameStateDataNode*)(node); const auto game_state_node = (CPlayerGameStateDataNode*)(node);
if (game_state_node->m_population_control_sphere_x == 712 || game_state_node->m_population_control_sphere_y == 712 if (game_state_node->m_is_overriding_population_control_sphere
|| game_state_node->m_population_control_sphere_z == 712) && !is_sane_override_pos(game_state_node->m_population_control_sphere_x,
game_state_node->m_population_control_sphere_y,
game_state_node->m_population_control_sphere_z))
{ {
notify::crash_blocked(sender, "invalid sector position (player game state node)"); notify::crash_blocked(sender, "invalid sector position (player game state node)");
return true; return true;
@ -784,7 +899,7 @@ namespace big
const auto train_node = (CTrainGameStateDataNode*)(node); const auto train_node = (CTrainGameStateDataNode*)(node);
if (train_node->m_track_id < 0 || train_node->m_track_id >= 27) if (train_node->m_track_id < 0 || train_node->m_track_id >= 27)
{ {
notify::crash_blocked(sender, "out of bound train track index"); notify::crash_blocked(sender, "out of bounds train track index");
return true; return true;
} }
break; break;
@ -808,6 +923,24 @@ namespace big
break; break;
} }
case sync_node_id("CPlayerGamerDataNode"):
{
const auto gamer_node = (CPlayerGamerDataNode*)(node);
if (sender_plyr)
{
if (gamer_node->m_clan_data.m_clan_id > 0 && gamer_node->m_clan_data.m_clan_id_2 > 0)
{
auto len = strlen(gamer_node->m_clan_data.m_clan_tag);
if (len <= 2)
{
session::add_infraction(sender_plyr, Infraction::SPOOFED_DATA);
}
}
}
break;
}
} }
} }
} }

View File

@ -4,6 +4,8 @@
#include "gta_util.hpp" #include "gta_util.hpp"
#include "hooking.hpp" #include "hooking.hpp"
#include "script_local.hpp" #include "script_local.hpp"
#include "services/players/player_service.hpp"
#include "util/misc.hpp"
#include "util/notify.hpp" #include "util/notify.hpp"
#include <script/globals/GlobalPlayerBD.hpp> #include <script/globals/GlobalPlayerBD.hpp>

View File

@ -1,57 +0,0 @@
#include "gta/script_handler.hpp"
#include "pointers.hpp"
#include "hooking.hpp"
namespace big
{
void hooking::hook_script_handler(CGameScriptHandler* handler)
{
Hash script_hash = handler->m_script_thread->m_context.m_script_hash;
{
auto hook = std::make_unique<vmt_hook>(handler, 20);
hook->hook(0, &hooks::script_handler_dtor);
hook->hook(6, &hooks::script_handler_is_networked);
hook->enable();
g_hooking->m_handler_hooks[handler] = std::move(hook);
}
}
CGameScriptHandler* hooks::create_script_handler(CGameScriptHandlerMgr* _this, void* unk)
{
auto handler = g_hooking->get_original<hooks::create_script_handler>()(_this, unk);
if (handler == nullptr || handler->m_script_thread == nullptr)
return handler;
g_hooking->hook_script_handler(handler);
return handler;
};
bool hooks::script_handler_is_networked(CGameScriptHandler* _this)
{
return *g_pointers->m_gta.m_is_session_started;
}
bool hooks::script_handler_dtor(CGameScriptHandler* _this, bool free_memory)
{
vmt_hook* hook;
if (g_hooking->m_handler_hooks.count(_this))
{
hook = g_hooking->m_handler_hooks[_this].get();
if (!hook)
return false;
hook->disable();
auto og_func = hook->get_original<decltype(&script_handler_dtor)>(0);
g_hooking->m_handler_hooks.erase(_this);
return og_func(_this, free_memory);
}
else
{
return false;
}
}
};

View File

@ -26,14 +26,5 @@ namespace big
strcpy(node->m_clan_data.m_clan_name, "Rockstar"); strcpy(node->m_clan_data.m_clan_name, "Rockstar");
} }
} }
node->m_is_cheater = g.spoofing.spoof_cheater;
// spoof r* dev and qa only when spoofing rid because every player in the session will send metrics if you join with that enabled
/*if (g.spoofing.spoof_rockstar_id)
{
node->m_is_rockstar_dev = g.spoofing.spoof_rockstar_dev;
node->m_is_rockstar_qa = g.spoofing.spoof_rockstar_qa;
}*/
} }
} }

View File

@ -36,6 +36,9 @@ namespace big
void native_invoker::end_call(rage::scrNativeHash hash) void native_invoker::end_call(rage::scrNativeHash hash)
{ {
if (!m_handlers_cached)
cache_handlers();
if (auto it = m_handler_cache.find(hash); it != m_handler_cache.end()) if (auto it = m_handler_cache.find(hash); it != m_handler_cache.end())
{ {
rage::scrNativeHandler handler = it->second; rage::scrNativeHandler handler = it->second;

View File

@ -5,6 +5,7 @@
#include "hooking.hpp" #include "hooking.hpp"
#include "native_hooks.hpp" #include "native_hooks.hpp"
#include "natives.hpp" #include "natives.hpp"
#include "util/notify.hpp"
#include "util/scripts.hpp" #include "util/scripts.hpp"
namespace big namespace big
@ -25,13 +26,10 @@ namespace big
void NETWORK_SET_THIS_SCRIPT_IS_NETWORK_SCRIPT(rage::scrNativeCallContext* src) void NETWORK_SET_THIS_SCRIPT_IS_NETWORK_SCRIPT(rage::scrNativeCallContext* src)
{ {
if (rage::scrThread::get() && rage::scrThread::get()->m_handler) if (src->get_arg<int>(2) >= 0x100)
{ {
if (auto hook = g_hooking->m_handler_hooks[(CGameScriptHandler*)rage::scrThread::get()->m_handler].get()) notify::crash_blocked(nullptr, "out of bounds instance id");
{ return;
hook->disable();
g_hooking->m_handler_hooks.erase((CGameScriptHandler*)rage::scrThread::get()->m_handler);
}
} }
NETWORK::NETWORK_SET_THIS_SCRIPT_IS_NETWORK_SCRIPT(src->get_arg<int>(0), src->get_arg<BOOL>(1), src->get_arg<int>(2)); NETWORK::NETWORK_SET_THIS_SCRIPT_IS_NETWORK_SCRIPT(src->get_arg<int>(0), src->get_arg<BOOL>(1), src->get_arg<int>(2));
@ -39,13 +37,11 @@ namespace big
void NETWORK_TRY_TO_SET_THIS_SCRIPT_IS_NETWORK_SCRIPT(rage::scrNativeCallContext* src) void NETWORK_TRY_TO_SET_THIS_SCRIPT_IS_NETWORK_SCRIPT(rage::scrNativeCallContext* src)
{ {
if (rage::scrThread::get() && rage::scrThread::get()->m_handler) if (src->get_arg<int>(2) >= 0x100)
{ {
if (auto hook = g_hooking->m_handler_hooks[(CGameScriptHandler*)rage::scrThread::get()->m_handler].get()) notify::crash_blocked(nullptr, "out of bounds instance id");
{ src->set_return_value<BOOL>(FALSE);
hook->disable(); return;
g_hooking->m_handler_hooks.erase((CGameScriptHandler*)rage::scrThread::get()->m_handler);
}
} }
src->set_return_value<BOOL>(NETWORK::NETWORK_TRY_TO_SET_THIS_SCRIPT_IS_NETWORK_SCRIPT(src->get_arg<int>(0), src->get_arg<BOOL>(1), src->get_arg<int>(2))); src->set_return_value<BOOL>(NETWORK::NETWORK_TRY_TO_SET_THIS_SCRIPT_IS_NETWORK_SCRIPT(src->get_arg<int>(0), src->get_arg<BOOL>(1), src->get_arg<int>(2)));

View File

@ -71,27 +71,26 @@ namespace big
} }
else else
{ {
if (SCRIPT::GET_HASH_OF_THIS_SCRIPT_NAME() == RAGE_JOAAT("freemode") && g.session.force_script_host) if (g.session.force_script_host && (g.session.fast_join || NETWORK::NETWORK_HAS_RECEIVED_HOST_BROADCAST_DATA()))
{ {
g_fiber_pool->queue_job([] { auto hash = SCRIPT::GET_HASH_OF_THIS_SCRIPT_NAME();
scripts::force_host(RAGE_JOAAT("freemode")); g_fiber_pool->queue_job([hash] {
if (auto script = gta_util::find_script_thread(RAGE_JOAAT("freemode")); script && script->m_net_component) scripts::force_host(hash);
if (auto script = gta_util::find_script_thread(hash); script && script->m_net_component)
script->m_net_component->block_host_migration(true); script->m_net_component->block_host_migration(true);
}); });
} }
if (SCRIPT::GET_HASH_OF_THIS_SCRIPT_NAME() == RAGE_JOAAT("fmmc_launcher") && g.session.force_script_host) if (SCRIPT::GET_HASH_OF_THIS_SCRIPT_NAME() == RAGE_JOAAT("freemode") && g.session.fast_join)
{ {
g_fiber_pool->queue_job([] {
scripts::force_host(RAGE_JOAAT("fmmc_launcher"));
if (auto script = gta_util::find_script_thread(RAGE_JOAAT("fmmc_launcher")); script && script->m_net_component)
script->m_net_component->block_host_migration(true);
});
}
scr_functions::set_freemode_session_active({}); scr_functions::set_freemode_session_active({});
src->set_return_value<BOOL>(TRUE); src->set_return_value<BOOL>(TRUE);
} }
else
{
src->set_return_value<BOOL>(NETWORK::NETWORK_HAS_RECEIVED_HOST_BROADCAST_DATA());
}
}
} }
} }
} }

View File

@ -842,15 +842,6 @@ namespace big
g_pointers->m_gta.m_sc_info = ptr.sub(4).rip().as<ScInfo*>(); g_pointers->m_gta.m_sc_info = ptr.sub(4).rip().as<ScInfo*>();
} }
}, },
// Create Script Handler
{
"CSH",
"48 8D 05 ? ? ? ? 4C 8D 0D ? ? ? ? 41 83 C8 FF 48 89 03 89 53 70 88 53 74 4C 89 4B 68 48 89 93",
[](memory::handle ptr)
{
g_pointers->m_gta.m_create_script_handler = *(ptr.add(3).rip().as<std::uint64_t**>() + 8);
}
},
// Invalid Decal Crash // Invalid Decal Crash
{ {
"IDC", "IDC",
@ -1223,6 +1214,15 @@ namespace big
g_pointers->m_gta.m_update_language = ptr.add(0x38).rip().as<functions::update_language>(); g_pointers->m_gta.m_update_language = ptr.add(0x38).rip().as<functions::update_language>();
} }
}, },
// Get Host Array Handler By Index
{
"GHAHBI",
"48 89 5C 24 08 48 89 6C 24 10 48 89 74 24 18 57 48 83 EC 20 8A 81 8F",
[](memory::handle ptr)
{
g_pointers->m_gta.m_get_host_array_handler_by_index = ptr.as<functions::get_host_array_handler_by_index>();
}
},
// Max Wanted Level // Max Wanted Level
{ {
"MWL", "MWL",
@ -1341,6 +1341,15 @@ namespace big
g_pointers->m_gta.m_script_vm_patch_5 = ptr; g_pointers->m_gta.m_script_vm_patch_5 = ptr;
g_pointers->m_gta.m_script_vm_patch_6 = ptr.add(0x26); g_pointers->m_gta.m_script_vm_patch_6 = ptr.add(0x26);
} }
},
// CTheScripts::GetHandlerCheckNetwork patch (aka Model Spawn Bypass)
{
"CTSHP",
"48 8B C8 FF 52 30 84 C0 74 05 48",
[](memory::handle ptr)
{
g_pointers->m_gta.m_model_spawn_bypass = ptr.add(8).as<PVOID>();
}
} }
>(); // don't leave a trailing comma at the end >(); // don't leave a trailing comma at the end

View File

@ -95,12 +95,6 @@ namespace big
bool script_connection::set_script_as_networked() bool script_connection::set_script_as_networked()
{ {
gta_util::execute_as_script(m_thread, [this] { gta_util::execute_as_script(m_thread, [this] {
if (auto hook = g_hooking->m_handler_hooks[(CGameScriptHandler*)m_thread->m_handler].get())
{
hook->disable();
g_hooking->m_handler_hooks.erase((CGameScriptHandler*)m_thread->m_handler);
}
NETWORK::NETWORK_SET_THIS_SCRIPT_IS_NETWORK_SCRIPT(32, true, m_instance_id); NETWORK::NETWORK_SET_THIS_SCRIPT_IS_NETWORK_SCRIPT(32, true, m_instance_id);
}); });

View File

@ -5,7 +5,6 @@
#include "network/ChatData.hpp" #include "network/ChatData.hpp"
#include "pointers.hpp" #include "pointers.hpp"
#include "script.hpp" #include "script.hpp"
#include "session.hpp"
#include <script/HudColor.hpp> #include <script/HudColor.hpp>
@ -31,14 +30,6 @@ namespace big::notify
{ {
g_notification_service->push_error("Protections", std::format("Blocked {} crash from unknown player", crash)); g_notification_service->push_error("Protections", std::format("Blocked {} crash from unknown player", crash));
} }
if (player)
{
if (auto plyr = g_player_service->get_by_id(player->m_player_id))
{
session::add_infraction(plyr, Infraction::TRIED_CRASH_PLAYER);
}
}
} }
// Shows a busy spinner till the value at the address equals the value passed or if timeout is hit // Shows a busy spinner till the value at the address equals the value passed or if timeout is hit

View File

@ -1,11 +1,12 @@
#pragma once #pragma once
#include "entity.hpp" #include "entity.hpp"
#include "natives.hpp"
#include "pointers.hpp"
#include "outfit.hpp"
#include "services/players/player_service.hpp"
#include "math.hpp"
#include "gta/enums.hpp" #include "gta/enums.hpp"
#include "local_player.hpp"
#include "math.hpp"
#include "natives.hpp"
#include "outfit.hpp"
#include "pointers.hpp"
#include "services/players/player_service.hpp"
namespace big::ped namespace big::ped
{ {
@ -498,14 +499,16 @@ namespace big::ped
inline void kill_ped(const Ped ped) inline void kill_ped(const Ped ped)
{ {
if (entity::take_control_of(ped)) if (entity::take_control_of(ped, 0))
PED::APPLY_DAMAGE_TO_PED(ped, PED::GET_PED_MAX_HEALTH(ped) * 2, false, 0); ENTITY::SET_ENTITY_HEALTH(ped, 0, self::ped);
} else
inline void kill_ped_by_relation(Ped ped, int relation_id)
{ {
if (PED::GET_RELATIONSHIP_BETWEEN_PEDS(ped, PLAYER::PLAYER_PED_ID()) == relation_id) auto ptr = g_pointers->m_gta.m_handle_to_ptr(ped);
kill_ped(ped); if (!ptr)
return;
g_pointers->m_gta.m_send_network_damage(g_player_service->get_self()->get_ped(), ptr, ptr->get_position(), 0, true, RAGE_JOAAT("weapon_explosion"), 10000.0f, 2, 0, (1 << 4), 0, 0, 0, false, false, true, true, nullptr);
}
} }
inline Ped spawn(ePedType pedType, Hash hash, Hash clone, Vector3 location, float heading, bool is_networked = true) inline Ped spawn(ePedType pedType, Hash hash, Hash clone, Vector3 location, float heading, bool is_networked = true)
@ -596,7 +599,8 @@ namespace big::ped
{ {
if (entity::take_control_of(ped)) if (entity::take_control_of(ped))
{ {
if (ENTITY::DOES_ENTITY_EXIST(veh)) { if (ENTITY::DOES_ENTITY_EXIST(veh))
{
if (math::distance_between_vectors(ENTITY::GET_ENTITY_COORDS(ped, 0), ENTITY::GET_ENTITY_COORDS(veh, 0)) < 15.f) if (math::distance_between_vectors(ENTITY::GET_ENTITY_COORDS(ped, 0), ENTITY::GET_ENTITY_COORDS(veh, 0)) < 15.f)
TASK::TASK_ENTER_VEHICLE(ped, veh, 10000, (int)seat, movespeed, 8, NULL); TASK::TASK_ENTER_VEHICLE(ped, veh, 10000, (int)seat, movespeed, 8, NULL);
else else

View File

@ -265,6 +265,14 @@ namespace big
script->m_net_component->block_host_migration(true); script->m_net_component->block_host_migration(true);
}); });
} }
if (ImGui::IsItemHovered())
ImGui::SetTooltip("This might break freemode missions and interiors. Use with caution");
ImGui::SameLine();
ImGui::Checkbox("Fast Join", &g.session.fast_join);
if (ImGui::IsItemHovered())
ImGui::SetTooltip("This WILL break jobs");
ImGui::Spacing(); ImGui::Spacing();

View File

@ -115,8 +115,10 @@ namespace big
false, false,
"Interior"); "Interior");
if (g_player_service->get_selected()->get_ped())
{
static float new_location[3]; static float new_location[3];
auto& current_location = *reinterpret_cast<float(*)[3]>(g_player_service->get_selected()->get_ped()->m_navigation->get_position()); auto& current_location = *reinterpret_cast<float(*)[3]>(g_player_service->get_selected()->get_ped()->get_position());
components::small_text("Custom TP"); components::small_text("Custom TP");
ImGui::SetNextItemWidth(400); ImGui::SetNextItemWidth(400);
@ -129,6 +131,7 @@ namespace big
{ {
std::copy(std::begin(current_location), std::end(current_location), std::begin(new_location)); std::copy(std::begin(current_location), std::end(current_location), std::begin(new_location));
} }
}
ImGui::EndListBox(); ImGui::EndListBox();
} }

View File

@ -23,7 +23,7 @@ namespace big
player_icons += FONT_ICON_HOST; player_icons += FONT_ICON_HOST;
if (plyr->is_friend()) if (plyr->is_friend())
player_icons += FONT_ICON_FRIEND; player_icons += FONT_ICON_FRIEND;
if (const auto ped = plyr->get_ped(); ped != nullptr && ped->m_ped_task_flag & (uint8_t)ePedTask::TASK_DRIVING) if (const auto ped = plyr->get_ped(); (ped != nullptr && ped->m_ped_task_flag & (uint8_t)ePedTask::TASK_DRIVING))
player_icons += FONT_ICON_VEHICLE; player_icons += FONT_ICON_VEHICLE;
const auto player_iconsc = player_icons.c_str(); const auto player_iconsc = player_icons.c_str();
@ -53,9 +53,11 @@ namespace big
g_gui_service->set_selected(tabs::PLAYER); g_gui_service->set_selected(tabs::PLAYER);
g.window.switched_view = true; g.window.switched_view = true;
} }
if (ImGui::IsItemHovered() && g_player_database_service->get_player_by_rockstar_id(plyr->get_net_data()->m_gamer_handle.m_rockstar_id) != nullptr) if (ImGui::IsItemHovered()
&& g_player_database_service->get_player_by_rockstar_id(plyr->get_net_data()->m_gamer_handle.m_rockstar_id) != nullptr)
{ {
auto sorted_player = g_player_database_service->get_player_by_rockstar_id(plyr->get_net_data()->m_gamer_handle.m_rockstar_id); auto sorted_player =
g_player_database_service->get_player_by_rockstar_id(plyr->get_net_data()->m_gamer_handle.m_rockstar_id);
if (!sorted_player->infractions.empty()) if (!sorted_player->infractions.empty())
{ {

View File

@ -14,7 +14,6 @@ namespace big
} }
ImGui::SeparatorText("Peds"); ImGui::SeparatorText("Peds");
// Nearby Ped Actions
components::button<ImVec2(110, 0), ImVec4(0.70196f, 0.3333f, 0.00392f, 1.f)>("Kill", [] { components::button<ImVec2(110, 0), ImVec4(0.70196f, 0.3333f, 0.00392f, 1.f)>("Kill", [] {
for (auto peds : entity::get_entities(false, true)) for (auto peds : entity::get_entities(false, true))
@ -26,10 +25,14 @@ namespace big
ImGui::SameLine(); ImGui::SameLine();
components::button<ImVec2(110, 0), ImVec4(0.76078f, 0.f, 0.03529f, 1.f)>("Kill Enemies", [] { components::button<ImVec2(110, 0), ImVec4(0.76078f, 0.f, 0.03529f, 1.f)>("Kill Enemies", [] {
for (auto peds : entity::get_entities(false, true)) for (auto ped : entity::get_entities(false, true))
{ {
if (!PED::IS_PED_A_PLAYER(peds)) if (!PED::IS_PED_A_PLAYER(ped))
ped::kill_ped_by_relation(peds, 4 || 5); {
auto relation = PED::GET_RELATIONSHIP_BETWEEN_PEDS(ped, self::ped);
if (relation == 4 || relation == 5)
ped::kill_ped(ped);
}
} }
}); });
@ -104,12 +107,13 @@ namespace big
quantity = list.size(); quantity = list.size();
remaining = quantity; remaining = quantity;
g_notification_service->push("Entity deletion", std::format("Deleting {} entities", quantity)); g_notification_service->push("Entity Deletion", std::format("Deleting {} entities", quantity));
deleting = true; deleting = true;
int failed = 0; int failed = 0;
for (auto ent : list) for (auto ent : list)
{ {
if (ent == self::ped) if (PED::IS_PED_A_PLAYER(ent))
continue; continue;
if (ENTITY::DOES_ENTITY_EXIST(ent)) if (ENTITY::DOES_ENTITY_EXIST(ent))
@ -122,8 +126,6 @@ namespace big
entity::delete_entity(ent); entity::delete_entity(ent);
} }
script::get_current()->yield(5ms);
if (ENTITY::DOES_ENTITY_EXIST(ent)) if (ENTITY::DOES_ENTITY_EXIST(ent))
failed++; failed++;
else else
@ -131,7 +133,7 @@ namespace big
} }
if (failed > 0) if (failed > 0)
g_notification_service->push_warning("Entity deletion", std::format("Failed deleting {} entities", failed)); g_notification_service->push_warning("Entity Deletion", std::format("Failed deleting {} entities", failed));
deleting = false; deleting = false;
}); });