Chat delay fix and improved crash protections (#1572)

* feat(protections): filter invalid sector position from the player game state data node
* feat(chat): bypass chat delay
* fix(world): fix auto disarm
* fix(chat): true instant messaging
This commit is contained in:
maybegreat48 2023-06-30 22:03:17 +00:00 committed by GitHub
parent 64afb5b0cb
commit 6ae19c062e
15 changed files with 191 additions and 198 deletions

View File

@ -25,7 +25,7 @@ namespace big
if (!PED::IS_PED_A_PLAYER(handle) && ENTITY::DOES_ENTITY_EXIST(PED::GET_PED_TARGET_FROM_COMBAT_PED(handle, false)))
{
if (entity::take_control_of(handle))
if (entity::take_control_of(handle, 0))
{
if (WEAPON::IS_PED_ARMED(handle, 1 | 2 | 4))
WEAPON::REMOVE_ALL_PED_WEAPONS(handle, false);

View File

@ -262,11 +262,10 @@ namespace big
} script_events{};
bool rid_join = false;
bool lessen_breakups = false; // disabled by default due to anticheat concerns
bool receive_pickup = false;
bool admin_check = true;
NLOHMANN_DEFINE_TYPE_INTRUSIVE(protections, script_events, rid_join, lessen_breakups, receive_pickup, admin_check)
NLOHMANN_DEFINE_TYPE_INTRUSIVE(protections, script_events, rid_join, receive_pickup, admin_check)
} protections{};
struct self

View File

@ -137,4 +137,6 @@ namespace big::functions
using get_entity_attached_to = rage::CDynamicEntity* (*)(rage::CDynamicEntity* entity);
using migrate_object = void (*)(CNetGamePlayer* player, rage::netObject* object, int type);
using handle_chat_message = void (*)(void* chat_data, void*, rage::rlGamerHandle* handle, const char* text, bool is_team);
}

View File

@ -1,8 +1,8 @@
#pragma once
#include "fwddec.hpp"
#include "pointers.hpp"
#include <base/atRTTI.hpp>
#include <base/atRTTI.hpp>
#include <cstdint>
#pragma pack(push, 1)
@ -212,6 +212,16 @@ namespace rage
{
return big::g_pointers->m_gta.m_write_bitbuf_array(this, array, size, 0);
}
void WriteString(char* string, int max_len)
{
auto len = std::min(max_len, (int)strlen(string) + 1);
bool extended = len > 127;
Write<bool>(extended, 1);
Write<int>(len, extended ? 15 : 7);
WriteArray(string, 8 * len);
}
bool ReadArray(PVOID array, int size)
{
return big::g_pointers->m_gta.m_read_bitbuf_array(this, array, size, 0);

View File

@ -176,9 +176,6 @@ namespace big
PVOID m_sort_session_details;
PVOID m_add_player_to_session;
PVOID m_send_chat_net_message;
PVOID m_process_matchmaking_find_response;
PVOID m_serialize_player_data_msg;
@ -259,6 +256,10 @@ namespace big
GenericPool** m_ped_pool{};
GenericPool** m_prop_pool{};
VehiclePool*** m_vehicle_pool{};
PVOID m_netfilter_handle_message{};
functions::handle_chat_message m_handle_chat_message{};
};
#pragma pack(pop)
static_assert(sizeof(gta_pointers) % 8 == 0, "Pointers are not properly aligned");

View File

@ -69,9 +69,7 @@ namespace big
detour_hook_helper::add<hooks::sort_session_details>("SSD", g_pointers->m_gta.m_sort_session_details);
detour_hook_helper::add<hooks::add_player_to_session>("APTS", g_pointers->m_gta.m_add_player_to_session);
detour_hook_helper::add<hooks::send_chat_message>("SCM", g_pointers->m_gta.m_send_chat_message);
detour_hook_helper::add<hooks::send_chat_net_message>("SCNM", g_pointers->m_gta.m_send_chat_net_message);
detour_hook_helper::add<hooks::process_matchmaking_find_response>("PMFR", g_pointers->m_gta.m_process_matchmaking_find_response);
detour_hook_helper::add<hooks::serialize_player_data_msg>("SJPD", g_pointers->m_gta.m_serialize_player_data_msg);
@ -118,6 +116,8 @@ namespace big
detour_hook_helper::add<hooks::allow_weapons_in_vehicle>("AWIV", g_pointers->m_gta.m_allow_weapons_in_vehicle);
detour_hook_helper::add<hooks::netfilter_handle_message>("NHM", g_pointers->m_gta.m_netfilter_handle_message);
g_hooking = this;
}

View File

@ -98,22 +98,16 @@ namespace big
static bool write_player_game_state_data_node(rage::netObject* player, CPlayerGameStateDataNode* node);
static void invalid_mods_crash_detour(int64_t a1, int64_t a2, int a3, char a4);
static std::int64_t constraint_attachment_crash(std::uintptr_t a1);
static uint64_t invalid_decal(uintptr_t a1, int a2);
static uint64_t task_parachute_object_0x270(uint64_t _this, int a2, int a3);
static bool update_presence_attribute_int(void* presence_data, int profile_index, char* attr, std::uint64_t value);
static bool update_presence_attribute_string(void* presence_data, int profile_index, char* attr, char* value);
static void serialize_ped_inventory_data_node(CPedInventoryDataNode* node, rage::CSyncDataBase* data);
static void serialize_vehicle_gadget_data_node(CVehicleGadgetDataNode* node, rage::CSyncDataBase* data);
static bool handle_join_request(Network* network, rage::snSession* session, rage::rlGamerInfo* player_info, CJoinRequestContext* ctx, BOOL is_transition_session);
static bool sort_session_details(SessionSortEntry* e1, SessionSortEntry* e2);
static bool add_player_to_session(rage::netConnectionManager* mgr, int receiver_msg_id, int* out_command_hndl, RemoteGamerInfoMsg* msg, int flags, void* unk);
static bool send_chat_net_message(rage::netConnectionManager* mgr, int receiver_msg_id, CMsgTextMessage* msg, int flags, void* unk);
static bool send_chat_message(void* team_mgr, rage::rlGamerInfo* local_gamer_info, char* message, bool is_team);
static bool process_matchmaking_find_response(void* _this, void* unused, rage::JSONNode* node, int* unk);
@ -137,8 +131,6 @@ namespace big
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* infinite_train_crash(void* carriage);
static bool received_array_update(rage::netArrayHandlerBase* array, CNetGamePlayer* sender, rage::datBitBuffer* buffer, int size, std::int16_t cycle);
static bool receive_pickup(rage::netObject* netobject, void* unk, CPed* ped);
@ -163,6 +155,7 @@ namespace big
static bool fipackfile_mount(rage::fiPackfile* this_, const char* mount_point);
static bool allow_weapons_in_vehicle(int64_t unk, int weaponinfo_group);
static int netfilter_handle_message(__int64 filter, char* message, int flags);
};
class minhook_keepalive

View File

@ -0,0 +1,14 @@
#include "hooking.hpp"
namespace big
{
int hooks::netfilter_handle_message(__int64 filter, char* message, int flags)
{
int* features = (int*)(filter + 0x24);
int old = *features;
*features = 0;
auto id = g_hooking->get_original<netfilter_handle_message>()(filter, message, flags);
*features = old;
return id;
}
}

View File

@ -1,16 +1,38 @@
#include "backend/command.hpp"
#include "backend/context/chat_command_context.hpp"
#include "gta/net_game_event.hpp"
#include "gta_util.hpp"
#include "hooking.hpp"
#include "packet.hpp"
#include "services/players/player_service.hpp"
namespace big
{
inline void gamer_handle_serialize(rage::rlGamerHandle& hnd, rage::datBitBuffer& buf)
{
constexpr int PC_PLATFORM = 3;
buf.Write<uint8_t>(PC_PLATFORM, 8);
buf.WriteInt64(*(int64_t*)&hnd.m_rockstar_id, 64);
buf.Write<uint8_t>(hnd.unk_0009, 8);
}
bool hooks::send_chat_message(void* team_mgr, rage::rlGamerInfo* local_gamer_info, char* message, bool is_team)
{
if (g.session.chat_commands && message[0] == g.session.chat_command_prefix)
command::process(std::string(message + 1), std::make_shared<chat_command_context>(g_player_service->get_self()));
return g_hooking->get_original<hooks::send_chat_message>()(team_mgr, local_gamer_info, message, is_team);
packet msg{};
msg.write_message(rage::eNetMessage::MsgTextMessage);
msg.m_buffer.WriteString(message, 256);
gamer_handle_serialize(g_player_service->get_self()->get_net_data()->m_gamer_handle, msg.m_buffer);
msg.write<bool>(is_team, 1);
for (auto& player : g_player_service->players())
if (player.second->get_net_game_player())
msg.send(player.second->get_net_game_player()->m_msg_id);
return true;
//return g_hooking->get_original<hooks::send_chat_message>()(team_mgr, local_gamer_info, message, is_team);
}
}

View File

@ -1,17 +0,0 @@
#include "gta_util.hpp"
#include "hooking.hpp"
#include "services/players/player_service.hpp"
#include <network/CMsgTextMessage.hpp>
#include <network/Network.hpp>
namespace big
{
bool hooks::send_chat_net_message(rage::netConnectionManager* mgr, int receiver_msg_id, CMsgTextMessage* msg, int flags, void* unk)
{
if (g.m_spoofed_peer_ids.contains(msg->m_peer_id))
msg->m_peer_id = g.m_spoofed_peer_ids[msg->m_peer_id];
return g_hooking->get_original<hooks::send_chat_net_message>()(mgr, receiver_msg_id, msg, flags, unk);
}
}

View File

@ -1,44 +0,0 @@
#include "gta_util.hpp"
#include "hooking.hpp"
#include <network/Network.hpp>
#include <network/RemoteGamerInfoMsg.hpp>
// https://stackoverflow.com/questions/8120062/generate-random-64-bit-integer
unsigned static rand256()
{
static unsigned const limit = RAND_MAX - RAND_MAX % 256;
unsigned result = rand();
while (result >= limit)
{
result = rand();
}
return result % 256;
}
unsigned long long static rand64bits()
{
unsigned long long results = 0ULL;
for (int count = 8; count > 0; --count)
{
results = 256U * results + rand256();
}
return results;
}
namespace big
{
bool hooks::add_player_to_session(rage::netConnectionManager* mgr, int receiver_msg_id, int* out_command_hndl, RemoteGamerInfoMsg* msg, int flags, void* unk)
{
if (msg->m_gamer_info.m_gamer_handle.m_rockstar_id
== g_local_player->m_player_info->m_net_player_data.m_gamer_handle.m_rockstar_id
&& gta_util::get_network()->m_game_session_ptr->is_host() && g.protections.lessen_breakups)
{
std::uint64_t peer_id = rand64bits();
g.m_spoofed_peer_ids.emplace(msg->m_gamer_info.m_peer_id_2, peer_id);
msg->m_gamer_info.m_peer_id_2 = peer_id;
}
return g_hooking->get_original<hooks::add_player_to_session>()(mgr, receiver_msg_id, out_command_hndl, msg, flags, unk);
}
}

View File

@ -135,6 +135,20 @@ namespace big
command::process(std::string(message + 1), std::make_shared<chat_command_context>(player));
else
g_lua_manager->trigger_event<"chat_message_received">(player->id(), message);
if (msgType == rage::eNetMessage::MsgTextMessage && g_pointers->m_gta.m_chat_data && player->get_net_data())
{
rage::rlGamerHandle temp{};
gamer_handle_deserialize(temp, buffer);
bool is_team = buffer.Read<bool>(1);
g_pointers->m_gta.m_handle_chat_message(*g_pointers->m_gta.m_chat_data,
nullptr,
&player->get_net_data()->m_gamer_handle,
message,
is_team);
return true;
}
}
break;
}

View File

@ -715,24 +715,6 @@ namespace big
g_pointers->m_gta.m_sort_session_details = ptr.sub(0x10).as<PVOID>();
}
},
// Add Player To Session
{
"APTS",
"E8 ? ? ? ? 48 8D 8D F0 01 00 00 8A D8",
[](memory::handle ptr)
{
g_pointers->m_gta.m_add_player_to_session = ptr.add(1).rip().as<PVOID>();
}
},
// Send Chat Net Message
{
"SCNM",
"E8 ? ? ? ? 41 FF C4 48 83 C5 08",
[](memory::handle ptr)
{
g_pointers->m_gta.m_send_chat_net_message = ptr.add(1).rip().as<PVOID>();
}
},
// Process Matchmaking Find Response
{
"PMFR",
@ -1213,6 +1195,24 @@ namespace big
g_pointers->m_gta.m_taskjump_constructor = ptr.as<PVOID>();
}
},
// NetFilter Handle Message
{
"NHM",
"40 55 56 57 41 54 41 55 41 56 41 57 48 81 EC 50 01 00 00 48 8D 6C 24 30",
[](memory::handle ptr)
{
g_pointers->m_gta.m_netfilter_handle_message = ptr.as<PVOID>();
}
},
// Handle Chat Message
{
"HCM",
"4D 85 C9 0F 84 8D",
[](memory::handle ptr)
{
g_pointers->m_gta.m_handle_chat_message = ptr.as<functions::handle_chat_message>();
}
},
// Max Wanted Level
{
"MWL",

View File

@ -80,4 +80,6 @@ namespace big::spam
spam_log.close();
}
}

View File

@ -41,12 +41,9 @@ namespace big
ImGui::Checkbox("BLOCK_RID_JOINING"_T.data(), &g.protections.rid_join);
if (ImGui::IsItemHovered())
ImGui::SetTooltip("BLOCK_RID_JOINING_DESCRIPTION"_T.data());
ImGui::Checkbox("LESSEN_BREAKUP_KICK"_T.data(), &g.protections.lessen_breakups);
if (ImGui::IsItemHovered())
ImGui::SetTooltip("LESSEN_BREAKUP_KICK_DESCRIPTION"_T.data());
ImGui::Checkbox("RECEIVE_PICKUP"_T.data(), &g.protections.receive_pickup);
if (ImGui::IsItemHovered())
ImGui::SetTooltip("This prevents any pickup from the ground such as unwanted money drops.\nAttention: Normal pickups are also no longer possible.");
ImGui::SetTooltip("This prevents the collection of pickups such as unwanted money bags\nNote: Normal pickups are also no longer possible to collect with this enabled");
ImGui::Checkbox("ADMIN_CHECK"_T.data(), &g.protections.admin_check);
ImGui::EndGroup();
}