diff --git a/classes.cpp b/classes.cpp index de17d5a..0776904 100644 --- a/classes.cpp +++ b/classes.cpp @@ -33,6 +33,7 @@ #include "enums/eExplosionTag.hpp" #include "enums/eHandlingType.hpp" #include "game_files/CGameConfig.hpp" +#include "game_files/GameDataHash.hpp" #include "misc/CTunables.hpp" #include "misc/vfx/TimecycleKeyframeData.hpp" #include "netsync/CProjectBaseSyncDataNode.hpp" @@ -113,6 +114,7 @@ #include "network/ChatData.hpp" #include "network/CJoinRequestContext.hpp" #include "network/ClanData.hpp" +#include "network/CMsgJoinRequest.hpp" #include "network/CMsgJoinResponse.hpp" #include "network/CMsgTextMessage.hpp" #include "network/CNetComplaintMgr.hpp" @@ -122,11 +124,13 @@ #include "network/MatchmakingAttributes.hpp" #include "network/MatchmakingId.hpp" #include "network/netObject.hpp" +#include "network/netObjectIds.hpp" #include "network/netPeerAddress.hpp" #include "network/netPlayer.hpp" #include "network/netPlayerMgrBase.hpp" #include "network/netTime.hpp" #include "network/Network.hpp" +#include "network/P2pSecurity.hpp" #include "network/RemoteGamerInfoMsg.hpp" #include "network/snConnectToPeerTask.hpp" #include "network/snSession.hpp" diff --git a/game_files/GameDataHash.hpp b/game_files/GameDataHash.hpp new file mode 100644 index 0000000..6046eda --- /dev/null +++ b/game_files/GameDataHash.hpp @@ -0,0 +1,13 @@ +#pragma once +#include "security/ObfVar.hpp" +#include + +#pragma pack(push, 8) +class GameDataHash +{ +public: + bool m_is_japanese_version; + std::array m_data; +}; +static_assert(sizeof(GameDataHash) == 0xF4); +#pragma pack(pop) \ No newline at end of file diff --git a/network/CMsgJoinRequest.hpp b/network/CMsgJoinRequest.hpp new file mode 100644 index 0000000..8c4cff6 --- /dev/null +++ b/network/CMsgJoinRequest.hpp @@ -0,0 +1,25 @@ +#pragma once +#include + +#include "game_files/GameDataHash.hpp" +#include "CNetGamePlayerDataMsg.hpp" +#include "rage/rlGamerHandle.hpp" + +#pragma pack(push, 8) +class CMsgJoinRequest +{ +public: + std::uint32_t m_version_number; + std::uint32_t m_flags; + std::uint32_t m_unk_zero; + std::uint32_t m_magic; + GameDataHash m_game_data_hash; + std::uint32_t m_dlc_hash; + std::uint32_t m_timeout_time; + std::uint32_t dword10C; + bool m_no_handle; + rage::rlGamerHandle m_gamer_handle; + CNetGamePlayerDataMsg m_player_data_msg; +}; +static_assert(sizeof(CMsgJoinRequest) == 0x168); +#pragma pack(pop) \ No newline at end of file diff --git a/network/CNetGamePlayerDataMsg.hpp b/network/CNetGamePlayerDataMsg.hpp index fa01b8c..29c7ab2 100644 --- a/network/CNetGamePlayerDataMsg.hpp +++ b/network/CNetGamePlayerDataMsg.hpp @@ -4,16 +4,16 @@ class datBitBuffer; -#pragma pack(push,8) +#pragma pack(push, 8) namespace rage { class playerDataMsg { public: - virtual ~playerDataMsg() = 0; - virtual int GetBufferSize() = 0; - virtual void Log() = 0; - virtual bool Serialize(datBitBuffer* buffer) = 0; - virtual bool Deserialize(datBitBuffer* buffer) = 0; + virtual ~playerDataMsg() = default; + virtual int GetBufferSize() { return 0; }; + virtual void Log() {}; + virtual bool Serialize(datBitBuffer* buffer) { return true; }; + virtual bool Deserialize(datBitBuffer* buffer) { return true; }; uint32_t m_game_version; //0x0008 uint32_t m_nat_type; //0x000C diff --git a/network/P2pSecurity.hpp b/network/P2pSecurity.hpp new file mode 100644 index 0000000..14e5abf --- /dev/null +++ b/network/P2pSecurity.hpp @@ -0,0 +1,67 @@ +#pragma once +#include "rage/rlGamerInfo.hpp" + +#pragma pack(push, 2) +namespace rage +{ + class SecurityPeer + { + public: +#pragma pack(push, 8) + struct Info + { + uint8_t platform; + rage::rlGamerHandle handle; + char name[16]; + }; +#pragma pack(pop) + + std::uint8_t gap0[80]; + int m_security_id_2; + std::uint8_t gap54[52]; + int m_time_initialized; + std::uint8_t gap8C[4]; + int dword90; + int m_security_id; + int gap98; + std::uint8_t gap9C[4]; + rage::netPeerAddress m_address; + rage::netPeerAddress m_real_address; + std::uint64_t qwordE0; // unk data from the bitbuffer + std::uint64_t qwordE8; + std::uint64_t qwordF0; + std::uint64_t m_peer_id; + rage::rlGamerHandle m_unverified_handle; + char m_dtls_cxn_type; + std::uint8_t gap111[3]; + char m_timeouts[0x40]; + std::uint8_t gap154[4]; + char m_decryption_lock[0x28]; + void* m_WolfSSL; + rage::SecurityPeer::Info m_info; + std::uint8_t gap1B0[48]; + rage::netPeerAddress m_last_provided_address; + int m_last_provided_security_id; + std::uint8_t gap204[44]; + char m_peer_query_stage; + std::uint8_t gap231[3]; + int m_get_peer_address_status; + std::uint8_t gap238[8]; + rage::netPeerAddress m_peer_query_result; + bool m_errored; + std::uint8_t m_dtls_cxn_establish_state; + char aaaa[2]; + int m_error_code; + std::uint8_t gap268[96]; // error queue + std::uint8_t m_info_requests; + std::uint8_t m_failed_decryption_attempts; + std::uint8_t gap2CA[6]; + int m_certificate_verify_error_code; + int m_certificate_verify_status; + std::uint8_t gap2D8[8]; + char m_flags; + std::uint8_t gap2E1[761]; + }; + static_assert(sizeof(rage::SecurityPeer) == 0x5DA); +} +#pragma pack(pop) \ No newline at end of file diff --git a/network/netConnection.hpp b/network/netConnection.hpp index 8e12e97..71d0db5 100644 --- a/network/netConnection.hpp +++ b/network/netConnection.hpp @@ -54,38 +54,59 @@ namespace rage uint64_t m_count; }; +#pragma pack(push, 8) + class netEvent + { + public: + enum class Type + { + ConnectionRequested = 0, // seems to be identical to rage::netConnection::InFrame + ConnectionError = 2, + ConnectionClosed = 3, + FrameReceived = 4, // rage::netConnection::InFrame + BandwidthExceeded = 6, + OutOfMemory = 7 + }; + + virtual ~netEvent() = default; + + virtual void destroy() = 0; + virtual Type get_event_type() = 0; + virtual uint32_t _0x18() = 0; + + std::uint32_t m_timestamp; // 0x0008 + char pad_0008[52]; // 0x000C + std::uint32_t m_msg_id; // 0x0040 + std::uint32_t m_connection_identifier; // 0x0044 + rage::netEvent* m_this; // 0x0048 + uint32_t m_peer_id; // 0x0050 + }; + static_assert(sizeof(rage::netEvent) == 0x58); + + class netEventConnectionError : public rage::netEvent + { + public: + std::uint64_t m_unk; // 0x0058 (always 2) + char m_data[0x80]; // 0x0060 + std::uint32_t m_size; // 0x00E0 + }; + static_assert(sizeof(rage::netEventConnectionError) == 0xE8); +#pragma pack(pop) + class netConnection { public: - class InFrame +#pragma pack(push, 8) + class InFrame : public rage::netEvent { public: - enum class EventType - { - ConnectionClosed = 3, - FrameReceived = 4, - BandwidthExceeded = 6, - OutOfMemory = 7 - }; - - virtual ~InFrame() = default; - - virtual void destroy() = 0; - virtual EventType get_event_type() = 0; - virtual uint32_t _0x18() = 0; - - uint32_t m_timestamp; //0x0008 - char pad_0008[52]; //0x000C - uint32_t m_msg_id; //0x0040 - uint32_t m_connection_identifier; //0x0044 - InFrame* m_this; //0x0048 - uint32_t m_peer_id; //0x0050 - char pad_0050[44]; //0x0058 - uint32_t m_length; //0x0080 - char pad_007C[4]; //0x0084 - void* m_data; //0x0088 + alignas(8) int m_security_id; // 0x0058 + rage::netPeerAddress m_peer_address; // 0x0060 + std::uint32_t m_length; // 0x0080 + void* m_data; // 0x0088 }; static_assert(sizeof(rage::netConnection::InFrame) == 0x90); +#pragma pack(pop) char gap0[8]; rage::netConnectionPeer* m_connection_peer; diff --git a/network/netObject.hpp b/network/netObject.hpp index 08f4467..459ec1f 100644 --- a/network/netObject.hpp +++ b/network/netObject.hpp @@ -4,6 +4,7 @@ #include "../netsync/netSyncTree.hpp" #include "../base/atRTTI.hpp" +#pragma pack(push, 4) class CObject; namespace rage { @@ -20,6 +21,8 @@ namespace rage bool m_wants_to_delete; //0x004D char pad_004E[1]; //0x004E bool m_should_not_be_delete; //0x004F + char pad_0050[0x38]; //0x0050 + int m_ownership_token; //0x0088 DEFINE_RAGE_RTTI(rage::netObject) @@ -129,5 +132,6 @@ namespace rage virtual void m_320() = 0; virtual void UpdatePendingVisibilityChanges() = 0; }; //Size: 0x0050 - static_assert(sizeof(netObject) == 0x50); + static_assert(sizeof(netObject) == 0x8C); // incorrect, but will do for now } +#pragma pack(pop) \ No newline at end of file diff --git a/network/netObjectIds.hpp b/network/netObjectIds.hpp new file mode 100644 index 0000000..4c223ae --- /dev/null +++ b/network/netObjectIds.hpp @@ -0,0 +1,62 @@ +#pragma once +#include + +#pragma pack(push, 4) +namespace rage +{ + class netObjectIds + { + public: + char gap0[41]; + char byte29; + int m_local_player_id; + int m_object_id_response_pending_players; + int m_last_object_id_response_time; + char gap38[4]; + uint16_t m_usable_object_ids[8000]; + int m_next_usable_object_id_write_slot; + int m_next_usable_object_id_read_slot; + int m_usable_object_id_count; + + inline bool is_object_id_usable(std::uint16_t id) + { + if (m_usable_object_id_count <= 0) + return false; + + int count = 0; + for (int i = m_next_usable_object_id_read_slot + 1; m_usable_object_ids[i % 8000] != id; i++) + if (++count > m_usable_object_id_count) + return false; + + return true; + } + + std::uint16_t get_usable_object_id() + { + int slot = ++m_next_usable_object_id_read_slot; + m_usable_object_id_count--; + if (slot == 8000) + slot = 0; + m_next_usable_object_id_read_slot = slot; + return m_usable_object_ids[slot]; + } + + // this operation is fundamentally unsupported by the data structure the IDs are stored in, unforeseen problems may occur + void remove_object_id(std::uint16_t id) + { + if (m_usable_object_id_count < 2) + return; // we need at least 2 items + + int count = 0; + int i; + for (i = m_next_usable_object_id_read_slot + 1; m_usable_object_ids[i % 8000] != id; i++) + if (++count > m_usable_object_id_count) + return; + + auto new_id = get_usable_object_id(); + if (new_id != id) + m_usable_object_ids[i % 8000] = new_id; + } + }; +} +#pragma pack(pop) \ No newline at end of file diff --git a/network/netPeerAddress.hpp b/network/netPeerAddress.hpp index 0127e58..23c2adc 100644 --- a/network/netPeerAddress.hpp +++ b/network/netPeerAddress.hpp @@ -14,7 +14,7 @@ static_assert(sizeof(netAddress) == 0x04); namespace rage { -#pragma pack(push, 4) +#pragma pack(push, 8) class netPeerAddress { public: diff --git a/network/snConnectToPeerTask.hpp b/network/snConnectToPeerTask.hpp index 8edc25b..ccca4fd 100644 --- a/network/snConnectToPeerTask.hpp +++ b/network/snConnectToPeerTask.hpp @@ -1,21 +1,26 @@ -#pragma once -#include - -namespace rage -{ - class snConnectToPeerTaskData - { - public: - int m_unk; - int m_reason; - uint64_t m_session_token; - }; - - class snConnectToPeerTaskResult - { - public: - char pad[0x10]{}; - int m_peer_id; - char pad2[0x400]{}; - }; +#pragma once +#include + +namespace rage +{ +#pragma pack(push, 8) + class snConnectToPeerTaskData + { + public: + std::uint8_t m_host_flag; + std::uint8_t m_connect_reason; + std::uint64_t m_session_token; + std::uint8_t m_flag2; + std::uint8_t m_flag3; + }; + static_assert(sizeof(rage::snConnectToPeerTaskData) == 0x18); +#pragma pack(pop) + + class snConnectToPeerTaskResult + { + public: + char pad[0x10]{}; + int m_peer_id; + char pad2[0x400]{}; + }; } \ No newline at end of file