diff --git a/src/backend/backend.cpp b/src/backend/backend.cpp index 6ce9bd0e..e2d0729f 100644 --- a/src/backend/backend.cpp +++ b/src/backend/backend.cpp @@ -21,12 +21,19 @@ namespace big { void bypass_battleye() { - auto old = g.session.spoof_host_token_type; - g.session.spoof_host_token_type = std::max(old, 1); - if (old != g.session.spoof_host_token_type) - g.session.spoof_host_token_dirty = true; - g.session.kick_host_when_forcing_host = true; - g.session.exclude_modders_from_kick_host = true; // useful + for (const auto& plyr : g_player_service->players() | std::ranges::views::values) + { + if (!plyr->is_host() || plyr->block_outgoing_clone_create) + continue; + + if (auto ped = g_player_service->get_self()->get_ped()) + { + entity::force_remove_network_entity(ped, plyr); + } + + plyr->block_outgoing_clone_create = true; + break; + } constexpr std::array valid_hashes = {1410389794, 967, 1523678325, 472, 0, 0, 1323039495, 0, 0, 1731098795, 2256610353, 17956, 414639110, 307143837, 3443181821, 0}; diff --git a/src/backend/looped/session/auto_kick_host.cpp b/src/backend/looped/session/auto_kick_host.cpp index 4bb000bb..183f3d45 100644 --- a/src/backend/looped/session/auto_kick_host.cpp +++ b/src/backend/looped/session/auto_kick_host.cpp @@ -26,6 +26,7 @@ namespace big static bool bLastKickHost = false; void looped::session_auto_kick_host() { + #if 0 bool kick_host = *g_pointers->m_gta.m_is_session_started && g.session.spoof_host_token_type != 0 && g.session.kick_host_when_forcing_host; if (kick_host && !bLastKickHost && is_next_in_queue()) [[unlikely]] { @@ -42,5 +43,6 @@ namespace big }); } bLastKickHost = kick_host; + #endif } } diff --git a/src/gta_pointers.hpp b/src/gta_pointers.hpp index 9fda7522..dddc4b7b 100644 --- a/src/gta_pointers.hpp +++ b/src/gta_pointers.hpp @@ -419,6 +419,8 @@ namespace big functions::get_last_keyboard_state m_get_last_keyboard_state; PVOID m_network_can_access_multiplayer; + + PVOID m_send_clone_create; }; #pragma pack(pop) static_assert(sizeof(gta_pointers) % 8 == 0, "Pointers are not properly aligned"); diff --git a/src/hooking/hooking.cpp b/src/hooking/hooking.cpp index 611cb33b..d7dac7c9 100644 --- a/src/hooking/hooking.cpp +++ b/src/hooking/hooking.cpp @@ -158,6 +158,8 @@ namespace big detour_hook_helper::add("NCAM", g_pointers->m_gta.m_network_can_access_multiplayer); + detour_hook_helper::add("SCC", g_pointers->m_gta.m_send_clone_create); + g_hooking = this; } diff --git a/src/hooking/hooking.hpp b/src/hooking/hooking.hpp index ff2775ce..9cd49ae4 100644 --- a/src/hooking/hooking.hpp +++ b/src/hooking/hooking.hpp @@ -215,6 +215,8 @@ namespace big static void* create_pool_item(GenericPool* pool); static bool network_can_access_multiplayer(void* a1, int* error); + + static void send_clone_create(CNetworkObjectMgr* _this, rage::netObject* object, CNetGamePlayer* player, rage::datBitBuffer* buffer); }; class minhook_keepalive diff --git a/src/hooks/misc/send_clone_create.cpp b/src/hooks/misc/send_clone_create.cpp new file mode 100644 index 00000000..6861950a --- /dev/null +++ b/src/hooks/misc/send_clone_create.cpp @@ -0,0 +1,17 @@ +#include "hooking/hooking.hpp" +#include "services/players/player_service.hpp" + +#include + +namespace big +{ + void hooks::send_clone_create(CNetworkObjectMgr* _this, rage::netObject* object, CNetGamePlayer* player, rage::datBitBuffer* buffer) + { + auto plyr = g_player_service->get_by_id(player->m_player_id); + + if (plyr->block_outgoing_clone_create) [[unlikely]] + return; + + g_hooking->get_original()(_this, object, player, buffer); + } +} \ No newline at end of file diff --git a/src/pointers.cpp b/src/pointers.cpp index 4d8af035..1144cacb 100644 --- a/src/pointers.cpp +++ b/src/pointers.cpp @@ -3,7 +3,7 @@ #include "gta_pointers_layout_info.hpp" #include "sc_pointers_layout_info.hpp" -#define GTA_VERSION_TARGET "1.69-3323" +#define GTA_VERSION_TARGET "1.69-3337" namespace big { @@ -1986,6 +1986,15 @@ namespace big { g_pointers->m_gta.m_network_can_access_multiplayer = ptr.add(1).rip().as(); } + }, + // Send Clone Create + { + "SCC", + "48 8B 02 4D 8B F8", + [](memory::handle ptr) + { + g_pointers->m_gta.m_send_clone_create = ptr.sub(0x1C).as(); + } } >(); // don't leave a trailing comma at the end diff --git a/src/services/players/player.hpp b/src/services/players/player.hpp index bd0fd5ad..1d5e7283 100644 --- a/src/services/players/player.hpp +++ b/src/services/players/player.hpp @@ -96,6 +96,8 @@ namespace big bool log_clones = false; bool log_network_events = false; + bool block_outgoing_clone_create = false; + bool trigger_desync_kick = false; bool trigger_end_session_kick = false; diff --git a/src/util/entity.cpp b/src/util/entity.cpp index 7fc4b5f1..f1793666 100644 --- a/src/util/entity.cpp +++ b/src/util/entity.cpp @@ -432,4 +432,27 @@ namespace big::entity if (auto object = (*g_pointers->m_gta.m_network_object_mgr)->find_object_by_id(net_id, true)) (*g_pointers->m_gta.m_network_object_mgr)->UnregisterNetworkObject(object, 8, true, true); } + + void force_remove_network_entity(rage::CDynamicEntity* entity, player_ptr for_player) + { + auto net_obj = entity->m_net_object; + + if (!net_obj) + return; + + char buf[0x200]{}; + rage::datBitBuffer remove_buf(buf, sizeof(buf)); + + remove_buf.Write(net_obj->m_object_id, 13); + remove_buf.Write(get_next_token_value(net_obj->m_ownership_token), 5); + + packet pack; + pack.write_message(rage::eNetMessage::MsgPackedReliables); + pack.write(4, 4); // remove + pack.write(1, 5); // msgs_written + pack.write(remove_buf.GetPosition(), 13); + pack.m_buffer.WriteArray(&buf, remove_buf.GetPosition()); + + pack.send(for_player->get_net_game_player()->m_msg_id); + } } diff --git a/src/util/entity.hpp b/src/util/entity.hpp index a2228f05..a1cfed83 100644 --- a/src/util/entity.hpp +++ b/src/util/entity.hpp @@ -24,4 +24,5 @@ namespace big::entity Entity get_entity_closest_to_middle_of_screen(rage::fwEntity** pointer = nullptr, std::vector ignore_entities = {}, bool include_veh = true, bool include_ped = true, bool include_prop = true, bool include_players = true); void force_remove_network_entity(rage::CDynamicEntity* entity, bool delete_locally = true); void force_remove_network_entity(std::uint16_t net_id, int ownership_token = -1, bool delete_locally = true); + void force_remove_network_entity(rage::CDynamicEntity* entity, player_ptr for_player); }