mirror of
https://github.com/YimMenu/YimMenuV2.git
synced 2026-10-10 11:53:14 +08:00
feat: handle net game event (#22)
This commit is contained in:
@@ -20,7 +20,7 @@ namespace YimMenu::Submenus
|
||||
|
||||
teleportGroup->AddItem(std::make_shared<CommandItem>("bringall"_J, "Bring All"));
|
||||
auto customPlayerTp = std::make_shared<Group>("", 1);
|
||||
customPlayerTp->AddItem(std::make_shared<Vector3CommandItem>("playertpcoord"_J, "##tpcoord"));
|
||||
customPlayerTp->AddItem(std::make_shared<Vector3CommandItem>("playertpcoord"_J, ""));
|
||||
customPlayerTp->AddItem(std::make_shared<CommandItem>("tpplayertocoordall"_J, "Teleport Everyone"));
|
||||
teleportGroup->AddItem(customPlayerTp);
|
||||
|
||||
|
||||
@@ -119,7 +119,7 @@ namespace YimMenu::Submenus
|
||||
teleportGroup->AddItem(std::make_shared<PlayerCommandItem>("tptoplayer"_J, "Teleport To"));
|
||||
teleportGroup->AddItem(std::make_shared<PlayerCommandItem>("bring"_J));
|
||||
auto customPlayerTp = std::make_shared<Group>("", 1);
|
||||
customPlayerTp->AddItem(std::make_shared<Vector3CommandItem>("playertpcoord"_J, "##tpcoord"));
|
||||
customPlayerTp->AddItem(std::make_shared<Vector3CommandItem>("playertpcoord"_J, ""));
|
||||
customPlayerTp->AddItem(std::make_shared<PlayerCommandItem>("tpplayertocoord"_J, "Teleport"));
|
||||
teleportGroup->AddItem(customPlayerTp);
|
||||
menu->AddItem(teleportGroup);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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<NetEventType>(event_id))
|
||||
{
|
||||
case NetEventType::WEAPON_DAMAGE_EVENT:
|
||||
{
|
||||
uint8_t damage_type = buffer.Read<uint8_t>(2);
|
||||
uint32_t weapon_type = buffer.Read<uint32_t>(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<uint32_t>(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);
|
||||
}
|
||||
}
|
||||
@@ -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<SCRIPT_EVENT*>(args);
|
||||
|
||||
switch (static_cast<ScriptEventIndex>(script_event->GetEventIndex()))
|
||||
{
|
||||
case ScriptEventIndex::Bounty:
|
||||
{
|
||||
SCRIPT_EVENT_BOUNTY* bounty = static_cast<SCRIPT_EVENT_BOUNTY*>(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;
|
||||
}
|
||||
}
|
||||
@@ -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<uint32_t>(5);
|
||||
uint32_t buffer_size = buffer.Read<uint32_t>(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<uint16_t>(7);
|
||||
uint32_t event_index = buffer.Read<uint32_t>(9);
|
||||
uint32_t event_handled_bits = buffer.Read<uint32_t>(8);
|
||||
uint32_t event_data_size = buffer.Read<uint32_t>(15);
|
||||
|
||||
if (buffer.Read<bool>(1))
|
||||
buffer.Read<uint32_t>(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;
|
||||
}
|
||||
|
||||
@@ -164,6 +164,17 @@ namespace YimMenu
|
||||
ReceiveNetMessage = ptr.Add(0xD).Add(1).Rip().As<PVOID>();
|
||||
});
|
||||
|
||||
constexpr auto netEventMgrPtrn = Pattern<"4C 8B 05 ? ? ? ? 44 0F B7 CA">("NetEventMgr");
|
||||
scanner.Add(netEventMgrPtrn, [this](PointerCalculator ptr) {
|
||||
NetEventMgr = ptr.Add(3).Rip().As<rage::netEventMgr**>();
|
||||
});
|
||||
|
||||
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<Functions::EventAck>();
|
||||
SendEventAck = ptr.Add(0x13).Add(1).Rip().As<Functions::SendEventAck>();
|
||||
});
|
||||
|
||||
if (!scanner.Scan())
|
||||
{
|
||||
LOG(FATAL) << "Some patterns could not be found, unloading.";
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
};
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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<int>(EVENT_INDEX); \
|
||||
__SizeOfEvent = sizeof(classType); \
|
||||
} \
|
||||
classType(const classType& other) \
|
||||
{ \
|
||||
memcpy(this, &other, sizeof(classType)); \
|
||||
EventIndex = static_cast<int>(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<int>(EVENT_INDEX); \
|
||||
} \
|
||||
classType(const classType& other) \
|
||||
{ \
|
||||
memcpy(this, &other, sizeof(classType)); \
|
||||
EventIndex = static_cast<int>(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);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user