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 "fiber_pool.hpp"
#include "hooking.hpp"
#include "util/notify.hpp"

View File

@ -1,6 +1,8 @@
#include "backend/looped/looped.hpp"
#include "core/scr_globals.hpp"
#include "gta/joaat.hpp"
#include "gta/net_array.hpp"
#include "gta_util.hpp"
#include "natives.hpp"
#include "script_global.hpp"
#include "services/players/player_service.hpp"
@ -8,6 +10,7 @@
// Credits: QuickNET
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"};
eTransitionState last_state = eTransitionState::TRANSITION_STATE_EMPTY;
@ -24,22 +27,51 @@ namespace big
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;
}
if (HUD::BUSYSPINNER_IS_ON())
if (state != eTransitionState::TRANSITION_STATE_FM_TRANSITION_CREATE_PLAYER && HUD::BUSYSPINNER_IS_ON())
{
HUD::BUSYSPINNER_OFF();
}
if ((int)state > 0 && (int)state < std::size(transition_states))
{
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(spinner_text.c_str());
HUD::END_TEXT_COMMAND_BUSYSPINNER_ON(5);
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::ADD_TEXT_COMPONENT_SUBSTRING_PLAYER_NAME(
std::format("Wait For Host Broadcast Data: {}%", (percent)).c_str());
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;

View File

@ -36,12 +36,6 @@ namespace big
// perform initial setup
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);
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(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()

View File

@ -7,14 +7,19 @@ namespace big
enum class Infraction
{
DESYNC_PROTECTION,
BREAKUP_KICK_DETECTED,
LOST_CONNECTION_KICK_DETECTED,
SPOOFED_ROCKSTAR_ID,
BREAKUP_KICK_DETECTED, // do not use
LOST_CONNECTION_KICK_DETECTED, // do not use
SPOOFED_ROCKSTAR_ID, // do not use
TRIGGERED_ANTICHEAT,
TRIED_CRASH_PLAYER,
TRIED_CRASH_PLAYER, // do not use
TRIED_KICK_PLAYER,
BLAME_EXPLOSION_DETECTED,
ATTACKING_WITH_GODMODE
BLAME_EXPLOSION_DETECTED, // do not use (for now)
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 = {
@ -26,6 +31,11 @@ namespace big
{Infraction::TRIED_CRASH_PLAYER, "Tried to crash you"},
{Infraction::TRIED_KICK_PLAYER, "Tried to kick you"},
{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 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{};
struct settings

View File

@ -6,6 +6,7 @@ class NetworkGameFilterMatchmakingComponent;
class sCloudFile;
class CPlayerGameStateDataNode;
class CVehicleGadgetDataNode;
class CGameScriptHandlerNetComponent;
enum eVehicleGadgetType : uint32_t;
namespace rage
@ -22,6 +23,7 @@ namespace rage
class rlScHandle;
class rlQueryPresenceAttributesContext;
enum class eThreadState : uint32_t;
class netArrayHandlerBase;
}
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 update_language = void (*)(bool);
using get_host_array_handler_by_index = rage::netArrayHandlerBase* (*)(CGameScriptHandlerNetComponent* component, int index);
}

View File

@ -29,46 +29,47 @@ namespace rage
class netSyncDataUnit_Dynamic
{
public:
virtual ~netSyncDataUnit_Dynamic() = default;// 0x00
virtual ~netSyncDataUnit_Dynamic() = default; // 0x00
virtual void _0x08() = 0;
virtual void _0x10() = 0;
virtual void set_data_counter(int index, uint16_t counter) = 0;// 0x18
virtual void set_data_counter(int index, uint16_t counter) = 0; // 0x18
virtual void reset_data_counter(int index) = 0;// 0x20
virtual void reset_data_counter(int index) = 0; // 0x20
// ...
int m_players_need_ack; // 0x08
int m_players_need_sync;// 0x0C
int m_players_need_ack; // 0x08
int m_players_need_sync; // 0x0C
};
class netSyncData_Dynamic
{
public:
virtual ~netSyncData_Dynamic() = default;// 0x00
virtual ~netSyncData_Dynamic() = default; // 0x00
virtual rage::datBitBuffer* _0x08() = 0;
virtual rage::datBitBuffer* _0x10() = 0;
virtual int get_num_receivers() = 0;// 0x18
virtual int get_num_receivers() = 0; // 0x18
virtual int _0x20() = 0;
virtual void _0x28() = 0;// same as get_sync_unit_for_element
virtual void _0x28() = 0; // same as get_sync_unit_for_element
virtual netSyncDataUnit_Dynamic* get_sync_unit_for_element(uint32_t element) = 0;// 0x30
virtual netSyncDataUnit_Dynamic* get_sync_unit_for_element(uint32_t element) = 0; // 0x30
// ...
};
#pragma pack(push, 1)
class netArrayHandlerBase
{
public:
virtual ~netArrayHandlerBase() = default;// 0x00
virtual ~netArrayHandlerBase() = default; // 0x00
virtual void _0x08() = 0;
@ -82,152 +83,134 @@ namespace rage
virtual void _0x30() = 0;
virtual void _0x38() = 0;//
virtual void _0x38() = 0; //
virtual void _0x40() = 0;//
virtual void _0x40() = 0; //
virtual int _0x48(CNetGamePlayer* player, int max_size, uint32_t* a3, uint32_t* a4) = 0;//
virtual int _0x48(CNetGamePlayer* player, int max_size, uint32_t* a3, uint32_t* a4) = 0; //
virtual int get_size(CNetGamePlayer* player, int max_size, uint32_t element) = 0;// 0x50
virtual int get_size(CNetGamePlayer* player, int max_size, uint32_t element) = 0; // 0x50
virtual int pack_array_data(CNetGamePlayer* player, rage::datBitBuffer* bit_buffer, uint16_t counter, uint32_t* elem_start, bool silent) = 0;// 0x58
virtual int pack_array_data(CNetGamePlayer* player, rage::datBitBuffer* bit_buffer, uint16_t counter, uint32_t* elem_start, bool silent) = 0; // 0x58
virtual void _0x60() = 0;//
virtual void _0x60() = 0; //
virtual bool _0x68(CNetGamePlayer* player) = 0;// is_player_out_of_scope or something like that
virtual bool _0x68(CNetGamePlayer* player) = 0; // is_player_out_of_scope or something like that
virtual void _0x70() = 0;//
virtual void _0x70() = 0; //
virtual bool can_send_update(CNetGamePlayer* player) = 0;// 0x78
virtual bool can_send_update(CNetGamePlayer* player) = 0; // 0x78
virtual void _0x80() = 0;//
virtual void _0x80() = 0; //
virtual void _0x88() = 0;//
virtual void _0x88() = 0; //
virtual void* get_identifier() = 0;// 0x90
virtual void* get_identifier() = 0; // 0x90
virtual void* _0x98() = 0;// same as get_identifier
virtual void* _0x98() = 0; // same as get_identifier
virtual void _0xA0() = 0;//
virtual void _0xA0() = 0; //
virtual bool can_verify_array_data() = 0;// 0xA8
virtual bool can_verify_array_data() = 0; // 0xA8
virtual void _0xB0() = 0;//
virtual void _0xB0() = 0; //
virtual void _0xB8() = 0;//
virtual void _0xB8() = 0; //
virtual void should_sync_element(uint32_t element) = 0;// 0xC0
virtual void should_sync_element(uint32_t element) = 0; // 0xC0
virtual void _0xC8() = 0;//
virtual void _0xC8() = 0; //
virtual void _0xD0() = 0;//
virtual void _0xD0() = 0; //
virtual bool are_all_elements_in_scope() = 0;// 0xD8
virtual bool are_all_elements_in_scope() = 0; // 0xD8
virtual void _0xE0() = 0;//
virtual void _0xE0() = 0; //
virtual void verify_array_data() = 0;// 0xE8
virtual void verify_array_data() = 0; // 0xE8
virtual void _0xF0() = 0;//
virtual void _0xF0() = 0; //
virtual char* get_name() = 0;// 0xF8
virtual char* get_name() = 0; // 0xF8
virtual bool is_local_player_owner_of_array() = 0;// 0x100
virtual bool is_local_player_owner_of_array() = 0; // 0x100
virtual CNetGamePlayer* get_owner_of_array() = 0;// 0x108
virtual CNetGamePlayer* get_owner_of_array() = 0; // 0x108
virtual void _0x110() = 0;
virtual uint32_t get_array_hash() = 0;
virtual int _0x120() = 0;// gets array size for hashing
virtual int _0x120() = 0; // gets array size for hashing
virtual netSyncData_Dynamic* _0x128() = 0;// same as get_dynamic_sync_data
virtual netSyncData_Dynamic* _0x128() = 0; // same as get_dynamic_sync_data
virtual netSyncData_Dynamic* get_dynamic_sync_data() = 0;// 0x130
virtual netSyncData_Dynamic* get_dynamic_sync_data() = 0; // 0x130
virtual void _0x138() = 0;
virtual bool is_element_in_scope(uint32_t element, CNetGamePlayer* player) = 0;// 0x140
virtual bool is_element_in_scope(uint32_t element, CNetGamePlayer* player) = 0; // 0x140
virtual int get_receiver_index_from_player(CNetGamePlayer*) = 0;// 0x148
virtual int get_receiver_index_from_player(CNetGamePlayer*) = 0; // 0x148
virtual void _0x150() = 0;
virtual void _0x158() = 0;
// pasted from fivem
virtual bool is_element_empty(uint32_t element) = 0;// 0x160
virtual bool is_element_empty(uint32_t element) = 0; // 0x160
virtual void set_element_empty(uint32_t element) = 0;// 0x168
virtual void set_element_empty(uint32_t element) = 0; // 0x168
virtual void write_element_index(rage::datBitBuffer& buffer, uint32_t) = 0;// 0x170
virtual void write_element_index(rage::datBitBuffer& buffer, uint32_t) = 0; // 0x170
virtual void read_element_index(rage::datBitBuffer& buffer, uint32_t&) = 0;// 0x178
virtual void read_element_index(rage::datBitBuffer& buffer, uint32_t&) = 0; // 0x178
virtual bool is_valid_index(uint32_t) = 0;// 0x180
virtual bool is_valid_index(uint32_t) = 0; // 0x180
virtual void recalculate_dirty_elements() = 0;// 0x188
virtual void recalculate_dirty_elements() = 0; // 0x188
virtual void reset_element_sync_data(uint32_t element) = 0;// 0x190
virtual void reset_element_sync_data(uint32_t element) = 0; // 0x190
virtual void do_post_read_processing() = 0;// 0x198
virtual void do_post_read_processing() = 0; // 0x198
virtual void do_post_element_read_processing(uint32_t element) = 0;// 0x1A0
virtual void do_post_element_read_processing(uint32_t element) = 0; // 0x1A0
virtual bool can_apply_element_data(uint32_t element, const rage::netPlayer& sender, bool force) = 0;// 0x1A8
virtual bool can_apply_element_data(uint32_t element, const rage::netPlayer& sender, bool force) = 0; // 0x1A8
virtual void extract_data_for_serializing(uint32_t elem) = 0;// 0x1B0
virtual void extract_data_for_serializing(uint32_t elem) = 0; // 0x1B0
virtual void write_element(rage::datBitBuffer& buffer, uint32_t elem, void* logger) = 0;// 0x1B8
virtual void write_element(rage::datBitBuffer& buffer, uint32_t elem, void* logger) = 0; // 0x1B8
virtual void read_element(rage::datBitBuffer& buffer, uint32_t elem, void* logger) = 0;// 0x1C0
virtual void read_element(rage::datBitBuffer& buffer, uint32_t elem, void* logger) = 0; // 0x1C0
virtual void log_element(uint32_t elem, void* logger) = 0;// 0x1C8
virtual void log_element(uint32_t elem, void* logger) = 0; // 0x1C8
virtual uint32_t get_current_element_size_in_bits(uint32_t elem) = 0;// 0x1D0
virtual uint32_t get_current_element_size_in_bits(uint32_t elem) = 0; // 0x1D0
virtual void apply_element_data(uint32_t element, const rage::netPlayer& sender) = 0;// 0x1D8
virtual void apply_element_data(uint32_t element, const rage::netPlayer& sender) = 0; // 0x1D8
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
netArrayHandlerBase* m_next;// 0x18
netArrayHandlerBase* m_next; // 0x18
uint8_t m_pad[100 - 0x18];// +8
uint8_t m_pad[100 - 0x18]; // +8
uint32_t m_hash;
uint8_t m_pad2[244 - 104];// +8
uint16_t m_index; // 244
uint16_t m_count; // 246
uint8_t m_max_elements; // 248
uint8_t m_element_size; // 249
uint8_t m_element_size_2; // 250
uint8_t m_pad3[13]; // 251
void* m_array; // 264
#if 0
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
uint8_t m_pad2[244 - 104]; // +8
uint16_t m_index; // 244
uint16_t m_count; // 246
uint8_t m_max_elements; // 248
uint8_t m_element_size; // 249
uint8_t m_element_size_2; // 250
uint8_t m_pad3[13]; // 251
void* m_array; // 264
uint8_t m_pad4[341 - (264 + 8)];
char m_flags; // 341
};
static_assert(sizeof(netArrayHandlerBase) == 272);
#pragma pack(pop)
static_assert(sizeof(netArrayHandlerBase) == 342);
}

View File

@ -203,8 +203,6 @@ namespace big
PVOID m_serialize_take_off_ped_variation_task;
PVOID m_create_script_handler;
functions::encode_session_info m_encode_session_info;
functions::decode_session_info m_decode_session_info;
functions::decode_peer_info m_decode_peer_info;
@ -263,6 +261,10 @@ namespace big
int* m_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)
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::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::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();
}
for (auto& thread : *g_pointers->m_gta.m_script_threads)
{
if (thread->m_handler)
hook_script_handler((CGameScriptHandler*)thread->m_handler);
}
MH_ApplyQueued();
m_enabled = true;
@ -171,7 +163,6 @@ namespace big
delete detour_hook_helper;
}
m_detour_hook_helpers.clear();
m_handler_hooks.clear();
}
hooking::detour_hook_helper::~detour_hook_helper()
@ -195,8 +186,6 @@ namespace big
bool hooks::run_script_threads(std::uint32_t ops_to_execute)
{
g_native_invoker.cache_handlers();
if (g_running)
{
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 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 void queue_dependency(void* dependency);
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)>();
}
void hook_script_handler(CGameScriptHandler* handler);
std::unordered_map<CGameScriptHandler*, std::unique_ptr<vmt_hook>> m_handler_hooks;
private:
bool m_enabled{};
minhook_keepalive m_minhook_keepalive;

View File

@ -1,12 +1,61 @@
#include "gta/net_game_event.hpp"
#include "hooking.hpp"
#include "services/players/player_service.hpp"
#include "util/globals.hpp"
#include "util/misc.hpp"
#include "util/session.hpp"
#include <entities/CDynamicEntity.hpp>
#include <script/globals/GPBD_FM.hpp>
#include <script/globals/GlobalPlayerBD.hpp>
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)
{
switch (net_event->get_type())
@ -21,7 +70,9 @@ namespace big
rage::sEntityDamagedData 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;
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(
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);
victim && victim->m_entity_type == 4 && reinterpret_cast<CPed*>(victim)->m_player_info)
if (PLAYER::IS_REMOTE_PLAYER_IN_NON_CLONED_VEHICLE(player->id()))
{
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);
}
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/players/player_service.hpp"
#include "util/notify.hpp"
#include "util/session.hpp"
#include <network/Network.hpp>
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)
{
@ -82,10 +90,9 @@ namespace big
net_player_data->m_gamer_handle.m_rockstar_id)));
}
auto id = player->m_player_id;
bool lock_session = g.session.lock_session;
auto id = player->m_player_id;
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 (plyr->get_net_data()->m_gamer_handle.m_rockstar_id != 0)
@ -106,32 +113,30 @@ namespace big
}
}
}
if (plyr->block_join)
{
if (g_player_service->get_self()->is_host())
{
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
{
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, {});
}
}
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, {});
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));
}
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/CPlayerCreationDataNode.hpp"
#include "netsync/nodes/player/CPlayerGameStateDataNode.hpp"
#include "netsync/nodes/player/CPlayerGamerDataNode.hpp"
#include "netsync/nodes/proximity_migrateable/CSectorDataNode.hpp"
#include "netsync/nodes/train/CTrainGameStateDataNode.hpp"
#include "netsync/nodes/vehicle/CVehicleCreationDataNode.hpp"
@ -25,6 +26,7 @@
#include "network/netObject.hpp"
#include "util/model_info.hpp"
#include "util/notify.hpp"
#include "util/session.hpp"
#include "vehicle/CVehicleModelInfo.hpp"
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};
inline CObject* get_game_object(rage::netObject* object)
{
return *(CObject**)((__int64)object + 0x50);
}
constexpr uint32_t valid_player_models[] = {
RAGE_JOAAT("mp_m_freemode_01"),
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)
{
@ -566,9 +603,11 @@ namespace big
{
if (!model_info::is_model_of_type(model, eModelType::Vehicle, eModelType::Unk133))
return true;
for (auto iterator : crash_vehicles)
if (iterator == model)
return true;
return false;
}
@ -576,28 +615,81 @@ namespace big
{
if (!model_info::get_model(model))
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))
return true;
for (auto iterator : crash_objects)
if (iterator == model)
return true;
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)
return false;
constexpr size_t reasonable_limit = 150;
size_t i = 0;
while (object && i < reasonable_limit)
auto target = g_pointers->m_gta.m_get_net_object(*g_pointers->m_gta.m_network_object_mgr, attached_to_net_id, false);
while (target)
{
if (object->m_net_object && object->m_net_object->m_object_id == attached_to_net_id)
if (target == object)
return true;
object = g_pointers->m_gta.m_get_entity_attached_to(object);
i++;
auto next = get_entity_attached_to(target->GetGameObject());
if (!next)
return false;
if (!next->m_net_object)
return false;
target = next->m_net_object;
}
return false;
@ -629,6 +721,26 @@ namespace big
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)
{
if (node->IsParentNode())
@ -641,10 +753,14 @@ namespace big
}
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))
{
if ((((CProjectBaseSyncDataNode*)node)->flags & 1) == 0)
continue;
switch (node_id)
{
case sync_node_id("CVehicleCreationDataNode"):
@ -681,17 +797,13 @@ namespace big
{
const auto attach_node = (CPhysicalAttachDataNode*)(node);
// TODO: Find a better method to avoid false positives
auto model_hash = get_game_object(object) ? get_game_object(object)->m_model_info->m_hash : 0;
if (attach_node->m_attached && attach_node->m_attached_to == object->m_object_id && (model_hash != RAGE_JOAAT("hauler2") && model_hash != RAGE_JOAAT("phantom3")))
if (attach_node->m_attached
&& is_attachment_infinite(object,
attach_node->m_attached_to,
attach_node->m_attach_bone,
attach_node->m_other_attach_bone))
{
// 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");
notify::crash_blocked(sender, "infinite physical attachment");
return true;
}
@ -715,16 +827,15 @@ namespace big
case sync_node_id("CPedAttachDataNode"):
{
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");
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;
}
@ -746,6 +857,7 @@ namespace big
notify::crash_blocked(sender, "invalid player model (appearance node)");
return true;
}
check_player_model(sender_plyr, player_appearance_node->m_model_hash);
break;
}
case sync_node_id("CPlayerCreationDataNode"):
@ -756,6 +868,7 @@ namespace big
notify::crash_blocked(sender, "invalid player model (creation node)");
return true;
}
check_player_model(sender_plyr, player_creation_node->m_model);
break;
}
case sync_node_id("CSectorDataNode"):
@ -771,8 +884,10 @@ namespace big
case sync_node_id("CPlayerGameStateDataNode"):
{
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
|| game_state_node->m_population_control_sphere_z == 712)
if (game_state_node->m_is_overriding_population_control_sphere
&& !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)");
return true;
@ -784,7 +899,7 @@ namespace big
const auto train_node = (CTrainGameStateDataNode*)(node);
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;
}
break;
@ -808,6 +923,24 @@ namespace big
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 "hooking.hpp"
#include "script_local.hpp"
#include "services/players/player_service.hpp"
#include "util/misc.hpp"
#include "util/notify.hpp"
#include <script/globals/GlobalPlayerBD.hpp>
@ -59,7 +61,7 @@ namespace big
}
}
scr_globals::globalplayer_bd.as<GlobalPlayerBD*>()->Entries[sender->m_player_id].RemoteWantedLevelPlayer = -1;// reset locally
scr_globals::globalplayer_bd.as<GlobalPlayerBD*>()->Entries[sender->m_player_id].RemoteWantedLevelPlayer = -1; // reset locally
}
if (array->m_array == scr_globals::gsbd.as<void*>() && *scr_globals::gsbd.as<eFreemodeState*>() == eFreemodeState::CLOSING)

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");
}
}
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)
{
if (!m_handlers_cached)
cache_handlers();
if (auto it = m_handler_cache.find(hash); it != m_handler_cache.end())
{
rage::scrNativeHandler handler = it->second;

View File

@ -236,4 +236,4 @@ BOOL APIENTRY DllMain(HMODULE hmod, DWORD reason, PVOID)
}
return true;
}
}

View File

@ -5,6 +5,7 @@
#include "hooking.hpp"
#include "native_hooks.hpp"
#include "natives.hpp"
#include "util/notify.hpp"
#include "util/scripts.hpp"
namespace big
@ -25,13 +26,10 @@ namespace big
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())
{
hook->disable();
g_hooking->m_handler_hooks.erase((CGameScriptHandler*)rage::scrThread::get()->m_handler);
}
notify::crash_blocked(nullptr, "out of bounds instance id");
return;
}
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)
{
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())
{
hook->disable();
g_hooking->m_handler_hooks.erase((CGameScriptHandler*)rage::scrThread::get()->m_handler);
}
notify::crash_blocked(nullptr, "out of bounds instance id");
src->set_return_value<BOOL>(FALSE);
return;
}
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,26 +71,25 @@ namespace big
}
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([] {
scripts::force_host(RAGE_JOAAT("freemode"));
if (auto script = gta_util::find_script_thread(RAGE_JOAAT("freemode")); script && script->m_net_component)
auto hash = SCRIPT::GET_HASH_OF_THIS_SCRIPT_NAME();
g_fiber_pool->queue_job([hash] {
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);
});
}
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({});
src->set_return_value<BOOL>(TRUE);
}
else
{
src->set_return_value<BOOL>(NETWORK::NETWORK_HAS_RECEIVED_HOST_BROADCAST_DATA());
}
scr_functions::set_freemode_session_active({});
src->set_return_value<BOOL>(TRUE);
}
}
}

View File

@ -842,15 +842,6 @@ namespace big
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
{
"IDC",
@ -1223,6 +1214,15 @@ namespace big
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
{
"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_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

View File

@ -95,12 +95,6 @@ namespace big
bool script_connection::set_script_as_networked()
{
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);
});

View File

@ -5,7 +5,6 @@
#include "network/ChatData.hpp"
#include "pointers.hpp"
#include "script.hpp"
#include "session.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));
}
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

View File

@ -1,11 +1,12 @@
#pragma once
#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 "local_player.hpp"
#include "math.hpp"
#include "natives.hpp"
#include "outfit.hpp"
#include "pointers.hpp"
#include "services/players/player_service.hpp"
namespace big::ped
{
@ -498,14 +499,16 @@ namespace big::ped
inline void kill_ped(const Ped ped)
{
if (entity::take_control_of(ped))
PED::APPLY_DAMAGE_TO_PED(ped, PED::GET_PED_MAX_HEALTH(ped) * 2, false, 0);
}
if (entity::take_control_of(ped, 0))
ENTITY::SET_ENTITY_HEALTH(ped, 0, self::ped);
else
{
auto ptr = g_pointers->m_gta.m_handle_to_ptr(ped);
if (!ptr)
return;
inline void kill_ped_by_relation(Ped ped, int relation_id)
{
if (PED::GET_RELATIONSHIP_BETWEEN_PEDS(ped, PLAYER::PLAYER_PED_ID()) == relation_id)
kill_ped(ped);
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)
@ -546,7 +549,7 @@ namespace big::ped
int drawable_id_max = PED::GET_NUMBER_OF_PED_DRAWABLE_VARIATIONS(ped, item.id) - 1;
if (drawable_id_max == -1)
continue;
int drawable_id = range(0, drawable_id_max);
int drawable_id = range(0, drawable_id_max);
int texture_id_max = PED::GET_NUMBER_OF_PED_TEXTURE_VARIATIONS(ped, item.id, drawable_id) - 1;
if (texture_id_max == -1)
continue;
@ -568,7 +571,7 @@ namespace big::ped
return nullptr;
}
inline bool load_animation_dict (const char* dict)
inline bool load_animation_dict(const char* dict)
{
if (STREAMING::HAS_ANIM_DICT_LOADED(dict))
return true;
@ -585,7 +588,7 @@ namespace big::ped
inline void ped_play_animation(Ped ped, const std::string_view& animDict, const std::string_view& animName, float speed = 4.f, float speedMultiplier = -4.f, int duration = -1, int flag = 0, float playbackRate = 0, bool lockPos = false)
{
if (load_animation_dict(animDict.data()))
TASK::TASK_PLAY_ANIM(ped, animDict.data(), animName.data(), speed, speedMultiplier, duration, flag, playbackRate, lockPos, lockPos, lockPos);
TASK::TASK_PLAY_ANIM(ped, animDict.data(), animName.data(), speed, speedMultiplier, duration, flag, playbackRate, lockPos, lockPos, lockPos);
}
/*
@ -596,7 +599,8 @@ namespace big::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)
TASK::TASK_ENTER_VEHICLE(ped, veh, 10000, (int)seat, movespeed, 8, NULL);
else

View File

@ -265,6 +265,14 @@ namespace big
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();

View File

@ -115,19 +115,22 @@ namespace big
false,
"Interior");
static float new_location[3];
auto& current_location = *reinterpret_cast<float(*)[3]>(g_player_service->get_selected()->get_ped()->m_navigation->get_position());
components::small_text("Custom TP");
ImGui::SetNextItemWidth(400);
ImGui::InputFloat3("##customlocation", new_location);
components::button("TP", [] {
teleport::teleport_player_to_coords(g_player_service->get_selected(), *reinterpret_cast<rage::fvector3*>(&new_location));
});
ImGui::SameLine();
if (ImGui::Button("Get current"))
if (g_player_service->get_selected()->get_ped())
{
std::copy(std::begin(current_location), std::end(current_location), std::begin(new_location));
static float new_location[3];
auto& current_location = *reinterpret_cast<float(*)[3]>(g_player_service->get_selected()->get_ped()->get_position());
components::small_text("Custom TP");
ImGui::SetNextItemWidth(400);
ImGui::InputFloat3("##customlocation", new_location);
components::button("TP", [] {
teleport::teleport_player_to_coords(g_player_service->get_selected(), *reinterpret_cast<rage::fvector3*>(&new_location));
});
ImGui::SameLine();
if (ImGui::Button("Get current"))
{
std::copy(std::begin(current_location), std::end(current_location), std::begin(new_location));
}
}
ImGui::EndListBox();

View File

@ -23,7 +23,7 @@ namespace big
player_icons += FONT_ICON_HOST;
if (plyr->is_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;
const auto player_iconsc = player_icons.c_str();
@ -53,9 +53,11 @@ namespace big
g_gui_service->set_selected(tabs::PLAYER);
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())
{

View File

@ -14,7 +14,6 @@ namespace big
}
ImGui::SeparatorText("Peds");
// Nearby Ped Actions
components::button<ImVec2(110, 0), ImVec4(0.70196f, 0.3333f, 0.00392f, 1.f)>("Kill", [] {
for (auto peds : entity::get_entities(false, true))
@ -26,10 +25,14 @@ namespace big
ImGui::SameLine();
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))
ped::kill_ped_by_relation(peds, 4 || 5);
if (!PED::IS_PED_A_PLAYER(ped))
{
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();
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;
int failed = 0;
for (auto ent : list)
{
if (ent == self::ped)
if (PED::IS_PED_A_PLAYER(ent))
continue;
if (ENTITY::DOES_ENTITY_EXIST(ent))
@ -122,8 +126,6 @@ namespace big
entity::delete_entity(ent);
}
script::get_current()->yield(5ms);
if (ENTITY::DOES_ENTITY_EXIST(ent))
failed++;
else
@ -131,7 +133,7 @@ namespace big
}
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;
});