Skip to content

Commit ac9d3db

Browse files
committed
feat(net/rdr3): extended object id manager
1 parent 476f550 commit ac9d3db

File tree

10 files changed

+1061
-57
lines changed

10 files changed

+1061
-57
lines changed

code/components/citizen-server-impl/src/state/ServerGameState.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7806,7 +7806,7 @@ static InitFunction initFunction([]()
78067806

78077807
constexpr bool canLengthHack =
78087808
#ifdef STATE_RDR3
7809-
false
7809+
true
78107810
#else
78117811
true
78127812
#endif

code/components/gta-net-five/include/rlNetBuffer.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,8 @@ class datBitBuffer
4343
return (m_curBit / 8) + leftoverBit;
4444
}
4545

46+
bool ReadBit(bool* bit);
47+
4648
bool ReadInteger(uint32_t* integer, int bits);
4749

4850
// NOTE: SIGNED

code/components/gta-net-five/src/CloneExperiments.cpp

Lines changed: 116 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -1398,41 +1398,17 @@ static CScenarioInfo* GetTaskScenarioInfo(void* task)
13981398

13991399
static constexpr int kPlayerNetIdLength = 16;
14001400

1401-
namespace rage
1402-
{
1403-
struct CSyncDataBase
1404-
{
1405-
char m_pad[24];
1406-
};
1407-
1408-
struct CSyncDataReader : CSyncDataBase
1409-
{
1410-
datBitBuffer* m_buffer;
1411-
};
1412-
1413-
struct CSyncDataWriter : CSyncDataBase
1414-
{
1415-
datBitBuffer* m_buffer;
1416-
};
1417-
1418-
struct CSyncDataSizeCalculator : CSyncDataBase
1419-
{
1420-
uint32_t m_size;
1421-
};
1422-
}
1423-
1424-
static hook::cdecl_stub<void(rage::CSyncDataBase*, uint8_t*, char*)> _syncDataBaseSerializePlayerIndex([]()
1401+
static hook::cdecl_stub<void(rage::CSyncDataBase*, uint8_t*, char*)> _syncDataBase_SerializePlayerIndex([]()
14251402
{
14261403
return hook::get_call(hook::get_pattern("0F B6 12 48 8B 05 ? ? ? ? 44", 0x1D));
14271404
});
14281405

1429-
static void (*g_origSyncDataReaderSerializePlayerIndex)(rage::CSyncDataReader*, uint8_t*, char*);
1430-
1431-
static void SyncDataReaderSerializePlayerIndex(rage::CSyncDataReader* syncData, uint8_t* index, char* prefix)
1406+
static void (*g_origSyncDataReader_SerializePlayerIndex)(rage::CSyncDataReader*, uint8_t*, char*);
1407+
static void SyncDataReader_SerializePlayerIndex(rage::CSyncDataReader* syncData, uint8_t* index, char* prefix)
14321408
{
14331409
if (!icgi->OneSyncEnabled)
14341410
{
1435-
return g_origSyncDataReaderSerializePlayerIndex(syncData, index, prefix);
1411+
return g_origSyncDataReader_SerializePlayerIndex(syncData, index, prefix);
14361412
}
14371413

14381414
uint32_t playerNetId = -1;
@@ -1448,16 +1424,15 @@ static void SyncDataReaderSerializePlayerIndex(rage::CSyncDataReader* syncData,
14481424

14491425
*index = playerIndex;
14501426

1451-
_syncDataBaseSerializePlayerIndex(syncData, index, prefix);
1427+
_syncDataBase_SerializePlayerIndex(syncData, index, prefix);
14521428
}
14531429

1454-
static void (*g_origSyncDataWriterSerializePlayerIndex)(rage::CSyncDataWriter*, uint8_t*, char*);
1455-
1456-
static void SyncDataWriterSerializePlayerIndex(rage::CSyncDataWriter* syncData, uint8_t* index, char* prefix)
1430+
static void (*g_origSyncDataWriter_SerializePlayerIndex)(rage::CSyncDataWriter*, uint8_t*, char*);
1431+
static void SyncDataWriter_SerializePlayerIndex(rage::CSyncDataWriter * syncData, uint8_t * index, char* prefix)
14571432
{
14581433
if (!icgi->OneSyncEnabled)
14591434
{
1460-
return g_origSyncDataWriterSerializePlayerIndex(syncData, index, prefix);
1435+
return g_origSyncDataWriter_SerializePlayerIndex(syncData, index, prefix);
14611436
}
14621437

14631438
uint16_t playerNetId = -1;
@@ -1467,25 +1442,98 @@ static void SyncDataWriterSerializePlayerIndex(rage::CSyncDataWriter* syncData,
14671442
playerNetId = g_netIdsByPlayer[player];
14681443
}
14691444

1470-
_syncDataBaseSerializePlayerIndex(syncData, index, prefix);
1445+
_syncDataBase_SerializePlayerIndex(syncData, index, prefix);
14711446

14721447
syncData->m_buffer->WriteUns(playerNetId, kPlayerNetIdLength);
14731448
}
14741449

1475-
static void (*g_origSyncDataSizeCalculatorSerializePlayerIndex)(rage::CSyncDataSizeCalculator*);
1476-
1477-
static void SyncDataSizeCalculatorSerializePlayerIndex(rage::CSyncDataSizeCalculator* syncData)
1450+
static void (*g_origSyncDataSizeCalculator_SerializePlayerIndex)(rage::CSyncDataSizeCalculator*);
1451+
static void SyncDataSizeCalculator_SerializePlayerIndex(rage::CSyncDataSizeCalculator* syncData)
14781452
{
14791453
static_assert(offsetof(rage::CSyncDataSizeCalculator, m_size) == 0x18);
14801454

14811455
if (!icgi->OneSyncEnabled)
14821456
{
1483-
return g_origSyncDataSizeCalculatorSerializePlayerIndex(syncData);
1457+
return g_origSyncDataSizeCalculator_SerializePlayerIndex(syncData);
14841458
}
14851459

14861460
syncData->m_size += kPlayerNetIdLength;
14871461
}
14881462

1463+
static void (*g_origSyncDataSizeCalculator_SerializeObjectId)(rage::CSyncDataSizeCalculator*);
1464+
static void SyncDataSizeCalculator_SerializeObjectId(rage::CSyncDataSizeCalculator* syncData)
1465+
{
1466+
if (!icgi->OneSyncEnabled)
1467+
{
1468+
return g_origSyncDataSizeCalculator_SerializeObjectId(syncData);
1469+
}
1470+
1471+
syncData->m_size += (icgi->OneSyncBigIdEnabled ? 16 : 13);
1472+
}
1473+
1474+
static hook::cdecl_stub<void(rage::CSyncDataBase*, uint16_t*, char*)> _syncDataBaseSerializeObjectId([]()
1475+
{
1476+
return hook::get_call(hook::get_pattern("0F B7 03 B9 3F 1F 00 00 66 FF C8 66 3B C1 76 04", -5));
1477+
});
1478+
1479+
static void (*g_origSyncDataWriter_SerializeObjectIdPrefix)(rage::CSyncDataWriter*, uint16_t*, char*);
1480+
static void SyncDataWriter_SerializeObjectIdPrefix(rage::CSyncDataWriter* syncData, uint16_t* objectId, char* prefix)
1481+
{
1482+
if (!icgi->OneSyncEnabled)
1483+
{
1484+
return g_origSyncDataWriter_SerializeObjectIdPrefix(syncData, objectId, prefix);
1485+
}
1486+
1487+
_syncDataBaseSerializeObjectId(syncData, objectId, prefix);
1488+
1489+
syncData->m_buffer->WriteUns(*objectId, icgi->OneSyncBigIdEnabled ? 16 : 13);
1490+
}
1491+
1492+
static void (*g_origSyncDataReader_SerializeObjectIdPrefix)(rage::CSyncDataReader*, uint16_t*, char*);
1493+
static void SyncDataReader_SerializeObjectIdPrefix(rage::CSyncDataReader* syncData, uint16_t* objectId, char* prefix)
1494+
{
1495+
if (!icgi->OneSyncEnabled)
1496+
{
1497+
return g_origSyncDataReader_SerializeObjectIdPrefix(syncData, objectId, prefix);
1498+
}
1499+
1500+
uint32_t netObjectId = 0;
1501+
1502+
if (syncData->m_buffer->ReadInteger(&netObjectId, icgi->OneSyncBigIdEnabled ? 16 : 13))
1503+
{
1504+
*objectId = netObjectId;
1505+
}
1506+
1507+
_syncDataBaseSerializeObjectId(syncData, objectId, prefix);
1508+
}
1509+
1510+
static void (*g_origSyncDataWriter_SerializeObjectIdStatic)(rage::CSyncDataWriter*, uint16_t*);
1511+
static void SyncDataWriter_SerializeObjectIdStatic(rage::CSyncDataWriter* syncData, uint16_t* objectId)
1512+
{
1513+
if (!icgi->OneSyncEnabled)
1514+
{
1515+
return g_origSyncDataWriter_SerializeObjectIdStatic(syncData, objectId);
1516+
}
1517+
1518+
syncData->m_buffer->WriteUns(*objectId, icgi->OneSyncBigIdEnabled ? 16 : 13);
1519+
}
1520+
1521+
static void (*g_origSyncDataReader_SerializeObjectIdStatic)(rage::CSyncDataReader*, uint16_t*);
1522+
static void SyncDataReader_SerializeObjectIdStatic(rage::CSyncDataReader* syncData, uint16_t* objectId)
1523+
{
1524+
if (!icgi->OneSyncEnabled)
1525+
{
1526+
return g_origSyncDataReader_SerializeObjectIdStatic(syncData, objectId);
1527+
}
1528+
1529+
uint32_t netObjectId = 0;
1530+
1531+
if (syncData->m_buffer->ReadInteger(&netObjectId, icgi->OneSyncBigIdEnabled ? 16 : 13))
1532+
{
1533+
*objectId = netObjectId;
1534+
}
1535+
}
1536+
14891537
static rlGamerInfo* (*g_origNetGamePlayerGetGamerInfo)(CNetGamePlayer*);
14901538

14911539
static rlGamerInfo* NetGamePlayerGetGamerInfo(CNetGamePlayer* self)
@@ -2024,22 +2072,43 @@ static HookFunction hookFunction([]()
20242072
hook::call(location, playerPedGetterStub.GetCode());
20252073
}
20262074

2027-
// patch SerializePlayerIndex methods of sync data reader/writer
2028-
MH_CreateHook(hook::get_pattern("80 3B 20 73 ? 65 4C 8B 0C", -0x2F), SyncDataReaderSerializePlayerIndex, (void**)&g_origSyncDataReaderSerializePlayerIndex);
2029-
MH_CreateHook(xbr::IsGameBuildOrGreater<1436>() ? hook::get_pattern("41 B2 3F 48 8D 54 24 30 44 88", -30) : hook::get_pattern("80 3A 20 48 8B D9 C6 44", -6), SyncDataWriterSerializePlayerIndex, (void**)&g_origSyncDataWriterSerializePlayerIndex);
2075+
// CSyncedDataWriter/CSyncedDataReader::SerializeObjectID (static).
2076+
MH_CreateHook(hook::get_pattern("66 3B C1 76 ? 33 C0 EB ? 0F B7 0A", -0xE), SyncDataWriter_SerializeObjectIdStatic, (void**)&g_origSyncDataWriter_SerializeObjectIdStatic);
2077+
MH_CreateHook(hook::get_call(hook::get_pattern("E8 ? ? ? ? 48 8D 53 0A")), SyncDataReader_SerializeObjectIdStatic, (void**)&g_origSyncDataReader_SerializeObjectIdStatic);
2078+
2079+
// CSyncedDataWriter/CSyncedDataReader::SerializeObjectID (prefixed).
2080+
MH_CreateHook(hook::get_pattern("E8 ? ? ? ? 0F B7 03 B9", -0x10), SyncDataWriter_SerializeObjectIdPrefix, (void**)&g_origSyncDataWriter_SerializeObjectIdPrefix);
2081+
MH_CreateHook(hook::get_pattern("B9 ? ? ? ? 49 8B 04 ? 8A 14 01", xbr::IsGameBuildOrGreater<1491>() ? -0x36 : -0x3E), SyncDataReader_SerializeObjectIdPrefix, (void**)&g_origSyncDataReader_SerializeObjectIdPrefix);
20302082

2031-
// also patch sync data size calculator allowing more bits
2083+
// patch sync data size calculator allowing more bits
20322084
{
2033-
auto sizeCalculatorVtable = hook::get_address<uintptr_t*>(hook::get_pattern("B8 BF FF 00 00 48 8B CF 66 21 87", 27));
2034-
g_origSyncDataSizeCalculatorSerializePlayerIndex = (decltype(g_origSyncDataSizeCalculatorSerializePlayerIndex))sizeCalculatorVtable[25];
2035-
hook::put(&sizeCalculatorVtable[25], (uintptr_t)SyncDataSizeCalculatorSerializePlayerIndex);
2085+
static constexpr int kSizeCalculatorSerializePlayerIndex = 25;
2086+
static constexpr int kSizeCalculatorSerializeObjectId1 = 26;
2087+
static constexpr int kSizeCalculatorSerializeObjectId2 = 27;
2088+
static constexpr int kSizeCalculatorSerializeObjectId3 = 28;
2089+
2090+
const auto sizeCalculatorVtable = hook::get_address<uintptr_t*>(hook::get_pattern("B8 BF FF 00 00 48 8B CF 66 21 87", 27));
2091+
2092+
g_origSyncDataSizeCalculator_SerializePlayerIndex = (decltype(g_origSyncDataSizeCalculator_SerializePlayerIndex))sizeCalculatorVtable[kSizeCalculatorSerializePlayerIndex];
2093+
hook::put(&sizeCalculatorVtable[kSizeCalculatorSerializePlayerIndex], (uintptr_t)SyncDataSizeCalculator_SerializePlayerIndex);
2094+
2095+
g_origSyncDataSizeCalculator_SerializeObjectId = (decltype(g_origSyncDataSizeCalculator_SerializeObjectId))sizeCalculatorVtable[kSizeCalculatorSerializeObjectId1];
2096+
hook::put(&sizeCalculatorVtable[kSizeCalculatorSerializeObjectId1], (uintptr_t)SyncDataSizeCalculator_SerializeObjectId);
2097+
hook::put(&sizeCalculatorVtable[kSizeCalculatorSerializeObjectId2], (uintptr_t)SyncDataSizeCalculator_SerializeObjectId);
2098+
hook::put(&sizeCalculatorVtable[kSizeCalculatorSerializeObjectId3], (uintptr_t)SyncDataSizeCalculator_SerializeObjectId);
20362099
}
20372100

2101+
// patch SerializePlayerIndex methods of sync data reader/writer
2102+
MH_CreateHook(hook::get_pattern("80 3B 20 73 ? 65 4C 8B 0C", -0x2F), SyncDataReader_SerializePlayerIndex, (void**)&g_origSyncDataReader_SerializePlayerIndex);
2103+
MH_CreateHook(xbr::IsGameBuildOrGreater<1436>() ? hook::get_pattern("41 B2 3F 48 8D 54 24 30 44 88", -30) : hook::get_pattern("80 3A 20 48 8B D9 C6 44", -6), SyncDataWriter_SerializePlayerIndex, (void**)&g_origSyncDataWriter_SerializePlayerIndex);
2104+
20382105
// attempt to get some information about CNetGamePlayer::GetGamerInfo related crashes
20392106
{
2107+
static constexpr int kNetGamePlayerGetGamerInfoIndex = 12;
2108+
20402109
auto netGamePlayerVtable = hook::get_address<uintptr_t*>(hook::get_pattern("E8 ? ? ? ? 33 F6 48 8D 05 ? ? ? ? 48 8D 8B", 10));
2041-
g_origNetGamePlayerGetGamerInfo = (decltype(g_origNetGamePlayerGetGamerInfo))netGamePlayerVtable[12];
2042-
hook::put(&netGamePlayerVtable[12], (uintptr_t)NetGamePlayerGetGamerInfo);
2110+
g_origNetGamePlayerGetGamerInfo = (decltype(g_origNetGamePlayerGetGamerInfo))netGamePlayerVtable[kNetGamePlayerGetGamerInfoIndex];
2111+
hook::put(&netGamePlayerVtable[kNetGamePlayerGetGamerInfoIndex], (uintptr_t)NetGamePlayerGetGamerInfo);
20432112
}
20442113

20452114
// patch CAIConditionIsLocalPlayerVisibleToAnyPlayer behavior to properly handle scoping players
@@ -2422,14 +2491,6 @@ static void SkipCopyIf1s(void* a1, void* a2, void* a3, void* a4, void* a5)
24222491
}
24232492
}
24242493

2425-
#ifdef IS_RDR3
2426-
static uint64_t CSyncedVarBase__GetMaxBits(void* self)
2427-
{
2428-
// object id length + 1 extra bit
2429-
return ((icgi->OneSyncBigIdEnabled) ? 16 : 13) + 1;
2430-
}
2431-
#endif
2432-
24332494
static HookFunction hookFunction2([]()
24342495
{
24352496
// 2 matches, 1st is data, 2nd is parent
@@ -2457,7 +2518,6 @@ static HookFunction hookFunction2([]()
24572518
auto location = hook::get_pattern<char>("49 89 43 C8 E8 ? ? ? ? 84 C0 0F 95 C0 48 83 C4 58", -0x3E);
24582519
hook::set_call(&g_origWriteDataNode, location + 0x42);
24592520
#endif
2460-
24612521
hook::jump(location, WriteDataNodeStub);
24622522
#endif
24632523
}

code/components/gta-net-five/src/rlNetBuffer.cpp

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,18 @@ static hook::cdecl_stub<bool(void*, uint32_t*, int)> _netBuffer_ReadInteger([]()
6565
#endif
6666
});
6767

68+
#ifdef IS_RDR3
69+
static hook::cdecl_stub<bool(void*, uint64_t, int)> _netBuffer_writeWord([]()
70+
{
71+
return hook::get_pattern("48 8B 74 24 ? 48 83 C4 ? 5F C3 90 B4 ? 8B C4", -0x63);
72+
});
73+
74+
static hook::cdecl_stub<bool(void*, uint8_t, int)> _netBuffer_writeByte([]()
75+
{
76+
return hook::get_pattern("48 8B 5C 24 ? 40 8A C7 48 8B 74 24 ? 48 83 C4 ? 5F C3 90 49 48 89 5C 24", -0x5B);
77+
});
78+
#endif
79+
6880
static void(*g_orig_netBuffer_ReadUnsigned)(void* a1, uint32_t* a2, int length, int a4);
6981
static void _netBuffer_ReadUnsigned(void* a1, uint32_t* a2, int length, int a4)
7082
{
@@ -105,10 +117,34 @@ namespace rage
105117
return _netBuffer_ReadInteger(this, integer, bits);
106118
}
107119

120+
bool datBitBuffer::ReadBit(bool* bit)
121+
{
122+
uint32_t result = 0;
123+
if (ReadInteger(&result, 1))
124+
{
125+
*bit = (result == 1);
126+
return true;
127+
}
128+
129+
return false;
130+
}
131+
108132
bool datBitBuffer::WriteInteger(uint32_t integer, int bits)
109133
{
110134
return _netBuffer_WriteInteger(this, integer, bits);
111135
}
136+
137+
#ifdef IS_RDR3
138+
bool datBitBuffer::WriteWord(uint64_t integer, int bits)
139+
{
140+
return _netBuffer_writeWord(this, integer, bits);
141+
}
142+
143+
bool datBitBuffer::WriteByte(uint8_t byte, int bits)
144+
{
145+
return _netBuffer_writeByte(this, byte, bits);
146+
}
147+
#endif
112148

113149
bool datBitBuffer::WriteUns(uint32_t integer, int bits)
114150
{

code/components/gta-net-rdr3/component.lua

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ return function()
1010
files {
1111
'components/gta-net-five/include/CloneManager.h',
1212
'components/gta-net-five/include/FramePacketHandler.h',
13+
'components/gta-net/five/include/ObjectIdPacketHandler.h',
1314
'components/gta-net-five/src/ClientRPC.cpp',
1415
'components/gta-net-five/src/CloneDebug.cpp',
1516
'components/gta-net-five/src/CloneExperiments.cpp',

code/components/gta-net-rdr3/include/netObjectMgr.h

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
#include <netObject.h>
44
#include <CrossBuildRuntime.h>
5+
#include <rlNetBuffer.h>
56

67
class CNetGamePlayer;
78

@@ -90,4 +91,35 @@ class netObjectMgr
9091

9192
static netObjectMgr* GetInstance();
9293
};
94+
95+
enum eSyncDataSerializer : uint8_t
96+
{
97+
SYNC_DATA_UNKNOWN = 0x0,
98+
SYNC_DATA_READER = 0x1,
99+
SYNC_DATA_WRITER = 0x2,
100+
SYNC_DATA_CLEANER = 0x3,
101+
SYNC_DATA_UNK = 0x4,
102+
};
103+
104+
struct CSyncDataBase
105+
{
106+
char m_pad1[8];
107+
eSyncDataSerializer m_type;
108+
char m_pad[15];
109+
};
110+
111+
struct CSyncDataReader : CSyncDataBase
112+
{
113+
datBitBuffer* m_buffer;
114+
};
115+
116+
struct CSyncDataWriter : CSyncDataBase
117+
{
118+
datBitBuffer* m_buffer;
119+
};
120+
121+
struct CSyncDataSizeCalculator : CSyncDataBase
122+
{
123+
uint32_t m_size;
124+
};
93125
}

code/components/gta-net-rdr3/include/rlNetBuffer.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,11 +43,17 @@ class datBitBuffer
4343
return (m_curBit / 8) + leftoverBit;
4444
}
4545

46+
bool ReadBit(bool* bit);
47+
4648
bool ReadInteger(uint32_t* integer, int bits);
4749

4850
// NOTE: SIGNED
4951
bool WriteInteger(uint32_t integer, int bits);
5052

53+
bool WriteWord(uint64_t integer, int bits);
54+
55+
bool WriteByte(uint8_t byte, int bits);
56+
5157
bool WriteUns(uint32_t integer, int bits);
5258

5359
bool WriteBit(bool bit);

0 commit comments

Comments
 (0)