diff --git a/src/game/frontend/submenus/Network.cpp b/src/game/frontend/submenus/Network.cpp index eaf9ba2..2aa07ee 100644 --- a/src/game/frontend/submenus/Network.cpp +++ b/src/game/frontend/submenus/Network.cpp @@ -20,7 +20,7 @@ namespace YimMenu::Submenus teleportGroup->AddItem(std::make_shared("bringall"_J, "Bring All")); auto customPlayerTp = std::make_shared("", 1); - customPlayerTp->AddItem(std::make_shared("playertpcoord"_J, "##tpcoord")); + customPlayerTp->AddItem(std::make_shared("playertpcoord"_J, "")); customPlayerTp->AddItem(std::make_shared("tpplayertocoordall"_J, "Teleport Everyone")); teleportGroup->AddItem(customPlayerTp); diff --git a/src/game/frontend/submenus/Player/Info.cpp b/src/game/frontend/submenus/Player/Info.cpp index 768a9aa..4a9f4ba 100644 --- a/src/game/frontend/submenus/Player/Info.cpp +++ b/src/game/frontend/submenus/Player/Info.cpp @@ -119,7 +119,7 @@ namespace YimMenu::Submenus teleportGroup->AddItem(std::make_shared("tptoplayer"_J, "Teleport To")); teleportGroup->AddItem(std::make_shared("bring"_J)); auto customPlayerTp = std::make_shared("", 1); - customPlayerTp->AddItem(std::make_shared("playertpcoord"_J, "##tpcoord")); + customPlayerTp->AddItem(std::make_shared("playertpcoord"_J, "")); customPlayerTp->AddItem(std::make_shared("tpplayertocoord"_J, "Teleport")); teleportGroup->AddItem(customPlayerTp); menu->AddItem(teleportGroup); diff --git a/src/game/hooks/Hooks.hpp b/src/game/hooks/Hooks.hpp index 8199e91..c11d3ec 100644 --- a/src/game/hooks/Hooks.hpp +++ b/src/game/hooks/Hooks.hpp @@ -13,6 +13,11 @@ namespace rage class datBitBuffer; } +namespace YimMenu +{ + class Player; +} + namespace YimMenu::Hooks { namespace SwapChain @@ -45,6 +50,8 @@ namespace YimMenu::Hooks namespace Network { extern void ReceiveNetMessage(void* a1, rage::netConnectionManager* mgr, rage::netEvent* event); + extern void ReceiveEvent(YimMenu::Player& player, uint16_t event_id, uint32_t event_index, uint32_t event_handled_bitset, rage::datBitBuffer& buffer); + extern bool HandleScriptedGameEvent(YimMenu::Player& player, int64_t* args, uint32_t args_size); } namespace Window diff --git a/src/game/hooks/Network/HandleNetGameEvent.cpp b/src/game/hooks/Network/HandleNetGameEvent.cpp new file mode 100644 index 0000000..65e9520 --- /dev/null +++ b/src/game/hooks/Network/HandleNetGameEvent.cpp @@ -0,0 +1,62 @@ +#include "core/util/Joaat.hpp" +#include "game/backend/Self.hpp" +#include "game/hooks/Hooks.hpp" +#include "game/pointers/Pointers.hpp" +#include "types/network/CNetGamePlayer.hpp" +#include "types/network/NetEventType.hpp" +#include "types/rage/datBitBuffer.hpp" + +namespace YimMenu::Hooks +{ + static void SendEventAck(rage::netEventMgr* event_mgr, CNetGamePlayer* source_player, CNetGamePlayer* target_player, uint32_t event_index, uint32_t event_handled_bits) + { + if (source_player->m_PlayerIndex != 255 && !Pointers.EventAck(0x778LL * source_player->m_PlayerIndex + (intptr_t)event_mgr + 0x2C408, target_player, event_index, event_handled_bits)) + { + Pointers.SendEventAck(event_mgr, source_player); + Pointers.EventAck((intptr_t)event_mgr + 0x2C408 + 0x778LL * source_player->m_PlayerIndex, target_player, event_index, event_handled_bits); + } + } + + static bool HandleNetGameEvent(Player& player, uint16_t event_id, rage::datBitBuffer& buffer) + { + switch (static_cast(event_id)) + { + case NetEventType::WEAPON_DAMAGE_EVENT: + { + uint8_t damage_type = buffer.Read(2); + uint32_t weapon_type = buffer.Read(32); + + if (weapon_type == "WEAPON_TRANQUILIZER"_J) + { + //player.AddDetection(); + return false; + } + + break; + } + case NetEventType::SCRIPTED_GAME_EVENT: + { + int64_t args[54]{}; + uint32_t args_size = buffer.Read(32); + + if (args_size > sizeof(args)) + return false; + + buffer.ReadArray(args, 8 * args_size); + + if (!Network::HandleScriptedGameEvent(player, args, args_size)) + return false; + + break; + } + } + + return true; + } + + void Network::ReceiveEvent(Player& player, uint16_t event_id, uint32_t event_index, uint32_t event_handled_bits, rage::datBitBuffer& buffer) + { + if (!HandleNetGameEvent(player, event_id, buffer)) + SendEventAck(*Pointers.NetEventMgr, player.GetHandle(), Self::GetPlayer().GetHandle(), event_index, event_handled_bits); + } +} \ No newline at end of file diff --git a/src/game/hooks/Network/HandleScriptedGameEvent.cpp b/src/game/hooks/Network/HandleScriptedGameEvent.cpp new file mode 100644 index 0000000..21de86a --- /dev/null +++ b/src/game/hooks/Network/HandleScriptedGameEvent.cpp @@ -0,0 +1,40 @@ +#include "game/backend/Self.hpp" +#include "game/hooks/Hooks.hpp" +#include "game/pointers/Pointers.hpp" +#include "types/script/ScriptEvent.hpp" + +namespace YimMenu::Hooks +{ + bool Network::HandleScriptedGameEvent(YimMenu::Player& player, int64_t* args, uint32_t args_size) + { + SCRIPT_EVENT* script_event = reinterpret_cast(args); + + switch (static_cast(script_event->GetEventIndex())) + { + case ScriptEventIndex::Bounty: + { + SCRIPT_EVENT_BOUNTY* bounty = static_cast(script_event); + + if (args_size != SCRIPT_EVENT_BOUNTY::GetSize()) + { + //player.AddDetection(); + return false; + } + + if (bounty->Target == Self::GetPed().GetHandle()) + { + return false; + } + + break; + } + case ScriptEventIndex::SendTextLabelSMS: + { + //player.AddDetection(); + return true; + } + } + + return true; + } +} \ No newline at end of file diff --git a/src/game/hooks/Network/ReceiveNetMessage.cpp b/src/game/hooks/Network/ReceiveNetMessage.cpp index b717c73..9c79004 100644 --- a/src/game/hooks/Network/ReceiveNetMessage.cpp +++ b/src/game/hooks/Network/ReceiveNetMessage.cpp @@ -45,6 +45,49 @@ namespace YimMenu::Hooks } break; } + case rage::netMessage::Type::PackedEvents: + { + auto player = Players::GetByMessageId(fr_evt->m_MsgId); + + if (!player) + break; + + uint32_t count = buffer.Read(5); + uint32_t buffer_size = buffer.Read(15); + + if (buffer_size > 7296) + buffer_size = 7296; + + int remaining = buffer_size; + + while (remaining >= 39) + { + int bits_read = buffer.m_BitsRead; + + uint16_t event_id = buffer.Read(7); + uint32_t event_index = buffer.Read(9); + uint32_t event_handled_bits = buffer.Read(8); + uint32_t event_data_size = buffer.Read(15); + + if (buffer.Read(1)) + buffer.Read(16); + + char event_data[4096 + 1]; + if (event_data_size) + { + buffer.ReadArray(event_data, event_data_size); + } + + rage::datBitBuffer event_buffer(event_data, sizeof(event_data), true); + event_buffer.m_MaxBit = event_data_size + 1; + + ReceiveEvent(player, event_id, event_index, event_handled_bits, event_buffer); + + remaining -= (int)buffer.m_BitsRead - bits_read; + } + + break; + } default: break; } diff --git a/src/game/pointers/Pointers.cpp b/src/game/pointers/Pointers.cpp index b996f0b..e05a8f3 100644 --- a/src/game/pointers/Pointers.cpp +++ b/src/game/pointers/Pointers.cpp @@ -164,6 +164,17 @@ namespace YimMenu ReceiveNetMessage = ptr.Add(0xD).Add(1).Rip().As(); }); + constexpr auto netEventMgrPtrn = Pattern<"4C 8B 05 ? ? ? ? 44 0F B7 CA">("NetEventMgr"); + scanner.Add(netEventMgrPtrn, [this](PointerCalculator ptr) { + NetEventMgr = ptr.Add(3).Rip().As(); + }); + + constexpr auto sendEventAckPtrn = Pattern<"84 C0 75 ? 89 EE 49 8D AD">("SendEventAck"); + scanner.Add(sendEventAckPtrn, [this](PointerCalculator ptr) { + EventAck = ptr.Sub(4).Rip().As(); + SendEventAck = ptr.Add(0x13).Add(1).Rip().As(); + }); + if (!scanner.Scan()) { LOG(FATAL) << "Some patterns could not be found, unloading."; diff --git a/src/game/pointers/Pointers.hpp b/src/game/pointers/Pointers.hpp index 456dd75..7ed3a2b 100644 --- a/src/game/pointers/Pointers.hpp +++ b/src/game/pointers/Pointers.hpp @@ -13,6 +13,7 @@ namespace rage class netSyncTree; class netObject; class netConnectionManager; + class netEventMgr; } class CPedFactory; class CNetGamePlayer; @@ -33,6 +34,8 @@ namespace YimMenu using QueuePacket = void(*)(rage::netConnectionManager* mgr, int msg_id, void* data, int size, int flags, std::uint16_t* out_seq_id); using GetNetObjectById = rage::netObject* (*)(uint16_t id); using RequestControl = void(*)(rage::netObject* object); + using EventAck = bool(*)(uintptr_t data, CNetGamePlayer* target_player, uint32_t event_index, uint32_t event_handled_bitset); + using SendEventAck = void(*)(rage::netEventMgr* event_manager, CNetGamePlayer* source_player); } struct PointerData @@ -69,6 +72,9 @@ namespace YimMenu Functions::RequestControl RequestControl; std::uint8_t* SpectatePatch; // used to patch the code that prevents you from spawning network objects when spectating PVOID ReceiveNetMessage; + rage::netEventMgr** NetEventMgr; + Functions::EventAck EventAck; + Functions::SendEventAck SendEventAck; }; struct Pointers : PointerData diff --git a/src/types/network/NetEventType.hpp b/src/types/network/NetEventType.hpp new file mode 100644 index 0000000..0841e19 --- /dev/null +++ b/src/types/network/NetEventType.hpp @@ -0,0 +1,92 @@ +#pragma once + +enum class NetEventType : uint16_t +{ + OBJECT_ID_FREED_EVENT, + OBJECT_ID_REQUEST_EVENT, + ARRAY_DATA_VERIFY_EVENT, + SCRIPT_ARRAY_DATA_VERIFY_EVENT, + REQUEST_CONTROL_EVENT, + GIVE_CONTROL_EVENT, + WEAPON_DAMAGE_EVENT, + REQUEST_PICKUP_EVENT, + REQUEST_MAP_PICKUP_EVENT, + GAME_CLOCK_EVENT, + GAME_WEATHER_EVENT, + RESPAWN_PLAYER_PED_EVENT, + GIVE_WEAPON_EVENT, + REMOVE_WEAPON_EVENT, + REMOVE_ALL_WEAPONS_EVENT, + VEHICLE_COMPONENT_CONTROL_EVENT, + FIRE_EVENT, + EXPLOSION_EVENT, + START_PROJECTILE_EVENT, + UPDATE_PROJECTILE_TARGET_EVENT, + REMOVE_PROJECTILE_ENTITY_EVENT, + BREAK_PROJECTILE_TARGET_LOCK_EVENT, + ALTER_WANTED_LEVEL_EVENT, + CHANGE_RADIO_STATION_EVENT, + RAGDOLL_REQUEST_EVENT, + PLAYER_TAUNT_EVENT, + PLAYER_CARD_STAT_EVENT, + DOOR_BREAK_EVENT, + SCRIPTED_GAME_EVENT, + REMOTE_SCRIPT_INFO_EVENT, + REMOTE_SCRIPT_LEAVE_EVENT, + MARK_AS_NO_LONGER_NEEDED_EVENT, + CONVERT_TO_SCRIPT_ENTITY_EVENT, + SCRIPT_WORLD_STATE_EVENT, + CLEAR_AREA_EVENT, + CLEAR_RECTANGLE_AREA_EVENT, + NETWORK_REQUEST_SYNCED_SCENE_EVENT, + NETWORK_START_SYNCED_SCENE_EVENT, + NETWORK_STOP_SYNCED_SCENE_EVENT, + NETWORK_UPDATE_SYNCED_SCENE_EVENT, + INCIDENT_ENTITY_EVENT, + GIVE_PED_SCRIPTED_TASK_EVENT, + GIVE_PED_SEQUENCE_TASK_EVENT, + NETWORK_CLEAR_PED_TASKS_EVENT, + NETWORK_START_PED_ARREST_EVENT, + NETWORK_START_PED_UNCUFF_EVENT, + NETWORK_SOUND_CAR_HORN_EVENT, + NETWORK_ENTITY_AREA_STATUS_EVENT, + NETWORK_GARAGE_OCCUPIED_STATUS_EVENT, + PED_CONVERSATION_LINE_EVENT, + SCRIPT_ENTITY_STATE_CHANGE_EVENT, + NETWORK_PLAY_SOUND_EVENT, + NETWORK_STOP_SOUND_EVENT, + NETWORK_PLAY_AIRDEFENSE_FIRE_EVENT, + NETWORK_BANK_REQUEST_EVENT, + NETWORK_AUDIO_BARK_EVENT, + REQUEST_DOOR_EVENT, + NETWORK_TRAIN_REPORT_EVENT, + NETWORK_TRAIN_REQUEST_EVENT, + NETWORK_INCREMENT_STAT_EVENT, + MODIFY_VEHICLE_LOCK_WORD_STATE_DATA, + MODIFY_PTFX_WORD_STATE_DATA_SCRIPTED_EVOLVE_EVENT, + REQUEST_PHONE_EXPLOSION_EVENT, + REQUEST_DETACHMENT_EVENT, + KICK_VOTES_EVENT, + GIVE_PICKUP_REWARDS_EVENT, + BLOW_UP_VEHICLE_EVENT, + NETWORK_SPECIAL_FIRE_EQUIPPED_WEAPON, + NETWORK_RESPONDED_TO_THREAT_EVENT, + NETWORK_SHOUT_TARGET_POSITION, + VOICE_DRIVEN_MOUTH_MOVEMENT_FINISHED_EVENT, + PICKUP_DESTROYED_EVENT, + UPDATE_PLAYER_SCARS_EVENT, + NETWORK_CHECK_EXE_SIZE_EVENT, + NETWORK_PTFX_EVENT, + NETWORK_PED_SEEN_DEAD_PED_EVENT, + REMOVE_STICKY_BOMB_EVENT, + NETWORK_CHECK_CODE_CRCS_EVENT, + INFORM_SILENCED_GUNSHOT_EVENT, + PED_PLAY_PAIN_EVENT, + CACHE_PLAYER_HEAD_BLEND_DATA_EVENT, + REMOVE_PED_FROM_PEDGROUP_EVENT, + REPORT_MYSELF_EVENT, + REPORT_CASH_SPAWN_EVENT, + ACTIVATE_VEHICLE_SPECIAL_ABILITY_EVENT, + BLOCK_WEAPON_SELECTION, + NETWORK_CHECK_CATALOG_CRC +}; \ No newline at end of file diff --git a/src/types/script/ScriptEvent.cpp b/src/types/script/ScriptEvent.cpp index 2a8460f..bba76aa 100644 --- a/src/types/script/ScriptEvent.cpp +++ b/src/types/script/ScriptEvent.cpp @@ -1,10 +1,7 @@ #include "ScriptEvent.hpp" #include "game/gta/Natives.hpp" -void SCRIPT_EVENT::Send() +void SCRIPT_EVENT::SendImpl(int size) { - auto size = __SizeOfEvent; - __SizeOfEvent = 0; SCRIPT::_SEND_TU_SCRIPT_EVENT_NEW(1, this, size / sizeof(std::uint64_t), PlayerBits, EventIndex); - __SizeOfEvent = size; } diff --git a/src/types/script/ScriptEvent.hpp b/src/types/script/ScriptEvent.hpp index 9f6317a..efa6908 100644 --- a/src/types/script/ScriptEvent.hpp +++ b/src/types/script/ScriptEvent.hpp @@ -1,18 +1,30 @@ #pragma once #include "types.hpp" -#define REGISTER_SCRIPT_EVENT(classType, indexType) \ - constexpr static auto EVENT_INDEX = ScriptEventIndex::indexType; \ - classType() \ - { \ - memset(this, 0, sizeof(classType)); EventIndex = static_cast(EVENT_INDEX); \ - __SizeOfEvent = sizeof(classType); \ - } \ - classType(const classType& other) \ - { \ - memcpy(this, &other, sizeof(classType)); \ - EventIndex = static_cast(EVENT_INDEX); \ - __SizeOfEvent = sizeof(classType); \ +#define REGISTER_SCRIPT_EVENT(classType, indexType) \ + constexpr static auto EVENT_INDEX = ScriptEventIndex::indexType; \ + classType() \ + { \ + memset(this, 0, sizeof(classType)); \ + EventIndex = static_cast(EVENT_INDEX); \ + } \ + classType(const classType& other) \ + { \ + memcpy(this, &other, sizeof(classType)); \ + EventIndex = static_cast(EVENT_INDEX); \ + } \ + static constexpr size_t GetSize() \ + { \ + return sizeof(classType); \ + } \ + inline void Send() \ + { \ + SendImpl(GetSize()); \ + } \ + inline void Send(int player) \ + { \ + SetPlayer(player); \ + SendImpl(GetSize()); \ } // I doubt rockstar would cycle this again, but best to keep this, just in case @@ -71,8 +83,7 @@ struct SCRIPT_EVENT { protected: SCR_HASH EventIndex; // 0x00 - Player SenderIndex; // 0x08 - int __SizeOfEvent; // 0x0C + PLAYER_INDEX SenderIndex; // 0x08 SCR_INT PlayerBits; // 0x10 public: @@ -106,14 +117,8 @@ public: PlayerBits |= (1 << player); } - // must be called in script context - void Send(); - - inline void Send(int player) - { - SetPlayer(player); - Send(); - } +protected: + void SendImpl(int size); }; static_assert(sizeof(SCRIPT_EVENT) == 3 * 8);