Skip to content

Commit cc05cd3

Browse files
committed
Update schema system
1 parent e0c0024 commit cc05cd3

File tree

4 files changed

+230
-222
lines changed

4 files changed

+230
-222
lines changed

src/cs2_sdk/entity/cbaseplayerpawn.h

Lines changed: 0 additions & 51 deletions
This file was deleted.

src/cs2_sdk/schema.cpp

Lines changed: 103 additions & 85 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/**
22
* =============================================================================
3-
* CS2Fixes
4-
* Copyright (C) 2023 Source2ZE
3+
* CS2ServerGUI
4+
* Copyright (C) 2023-2025 Source2ZE
55
* =============================================================================
66
*
77
* This program is free software; you can redistribute it and/or modify it under
@@ -19,116 +19,134 @@
1919

2020
#include "schema.h"
2121

22-
#include "schemasystem/schemasystem.h"
23-
#include "tier1/utlmap.h"
24-
#include "tier0/memdbgon.h"
2522
#include "entity/cbaseentity.h"
26-
#include "interfaces.h"
27-
#include "../utils/plat.h"
23+
#include "utils/plat.h"
24+
#include "schemasystem/schemasystem.h"
2825

29-
extern CGlobalVars *gpGlobals;
26+
#include "tier0/memdbgon.h"
3027

31-
using SchemaKeyValueMap_t = CUtlMap<uint32_t, SchemaKey>;
32-
using SchemaTableMap_t = CUtlMap<uint32_t, SchemaKeyValueMap_t*>;
28+
using SchemaKeyValueMap_t = std::map<uint32_t, SchemaKey>;
29+
using SchemaTableMap_t = std::map<uint32_t, SchemaKeyValueMap_t>;
3330

31+
static constexpr uint32_t g_ChainKey = hash_32_fnv1a_const("__m_pChainEntity");
3432

3533
static bool IsFieldNetworked(SchemaClassFieldData_t& field)
3634
{
37-
for (int i = 0; i < field.m_nStaticMetadataCount; i++)
38-
{
39-
static auto networkEnabled = hash_32_fnv1a_const("MNetworkEnable");
40-
if (networkEnabled == hash_32_fnv1a_const(field.m_pStaticMetadata[i].m_pszName))
41-
return true;
42-
}
35+
for (int i = 0; i < field.m_nStaticMetadataCount; i++)
36+
{
37+
static auto networkEnabled = hash_32_fnv1a_const("MNetworkEnable");
38+
if (networkEnabled == hash_32_fnv1a_const(field.m_pStaticMetadata[i].m_pszName))
39+
return true;
40+
}
41+
42+
return false;
43+
}
4344

44-
return false;
45-
}
45+
// Try to recursively find __m_pChainEntity in base classes
46+
// (e.g. CCSGameRules -> CTeamplayRules -> CMultiplayRules -> CGameRules, in this case it's in CGameRules)
47+
static void InitChainOffset(SchemaClassInfoData_t *pClassInfo, SchemaKeyValueMap_t &keyValueMap)
48+
{
49+
short fieldsSize = pClassInfo->m_nFieldCount;
50+
SchemaClassFieldData_t* pFields = pClassInfo->m_pFields;
51+
52+
for (int i = 0; i < fieldsSize; ++i)
53+
{
54+
SchemaClassFieldData_t& field = pFields[i];
55+
56+
if (hash_32_fnv1a_const(field.m_pszName) != g_ChainKey)
57+
continue;
58+
59+
std::pair<uint32_t, SchemaKey> keyValuePair;
60+
keyValuePair.first = g_ChainKey;
61+
keyValuePair.second.offset = field.m_nSingleInheritanceOffset;
62+
keyValuePair.second.networked = IsFieldNetworked(field);
63+
64+
keyValueMap.insert(keyValuePair);
65+
return;
66+
}
67+
68+
// Not the base class yet, keep looking
69+
if (pClassInfo->m_nBaseClassCount)
70+
return InitChainOffset(pClassInfo->m_pBaseClasses[0].m_pClass, keyValueMap);
71+
}
4672

47-
static bool InitSchemaFieldsForClass(SchemaTableMap_t *tableMap, const char* className, uint32_t classKey)
73+
static void InitSchemaKeyValueMap(SchemaClassInfoData_t *pClassInfo, SchemaKeyValueMap_t& keyValueMap)
4874
{
49-
CSchemaSystemTypeScope* pType = Interfaces::g_pSchemaSystem2->FindTypeScopeForModule(MODULE_PREFIX "server" MODULE_EXT);
75+
short fieldsSize = pClassInfo->m_nFieldCount;
76+
SchemaClassFieldData_t* pFields = pClassInfo->m_pFields;
5077

51-
if (!pType)
52-
return false;
78+
for (int i = 0; i < fieldsSize; ++i)
79+
{
80+
SchemaClassFieldData_t& field = pFields[i];
5381

54-
SchemaClassInfoData_t* pClassInfo = pType->FindDeclaredClass(className).Get();
82+
#ifdef _DEBUG
83+
Message("%s::%s found at -> 0x%X - %llx\n", pClassInfo->m_pszName, field.m_pszName, field.m_nSingleInheritanceOffset, &field);
84+
#endif
5585

56-
if (!pClassInfo)
57-
{
58-
SchemaKeyValueMap_t *map = new SchemaKeyValueMap_t(0, 0, DefLessFunc(uint32_t));
59-
tableMap->Insert(classKey, map);
86+
std::pair<uint32_t, SchemaKey> keyValuePair;
87+
keyValuePair.first = hash_32_fnv1a_const(field.m_pszName);
88+
keyValuePair.second.offset = field.m_nSingleInheritanceOffset;
89+
keyValuePair.second.networked = IsFieldNetworked(field);
6090

61-
Warning("InitSchemaFieldsForClass(): '%s' was not found!\n", className);
62-
return false;
63-
}
91+
keyValueMap.insert(keyValuePair);
92+
}
6493

65-
short fieldsSize = pClassInfo->m_nFieldCount;
66-
SchemaClassFieldData_t* pFields = pClassInfo->m_pFields;
94+
// If this is a child class there might be a parent class with __m_pChainEntity
95+
if (!keyValueMap.contains(g_ChainKey) && pClassInfo->m_nBaseClassCount)
96+
InitChainOffset(pClassInfo->m_pBaseClasses[0].m_pClass, keyValueMap);
97+
}
6798

68-
SchemaKeyValueMap_t *keyValueMap = new SchemaKeyValueMap_t(0, 0, DefLessFunc(uint32_t));
69-
keyValueMap->EnsureCapacity(fieldsSize);
70-
tableMap->Insert(classKey, keyValueMap);
99+
static bool InitSchemaFieldsForClass(SchemaTableMap_t& tableMap, const char* className, uint32_t classKey)
100+
{
101+
CSchemaSystemTypeScope* pType = g_pSchemaSystem->FindTypeScopeForModule(MODULE_PREFIX "server" MODULE_EXT);
71102

72-
for (int i = 0; i < fieldsSize; ++i)
73-
{
74-
SchemaClassFieldData_t& field = pFields[i];
103+
if (!pType)
104+
return false;
75105

76-
#ifdef _DEBUG
77-
Message("%s::%s found at -> 0x%X - %llx\n", className, field.m_pszName, field.m_nSingleInheritanceOffset, &field);
78-
#endif
106+
SchemaClassInfoData_t* pClassInfo = pType->FindDeclaredClass(className).Get();
107+
108+
if (!pClassInfo)
109+
{
110+
SchemaKeyValueMap_t map;
111+
tableMap.insert(std::make_pair(classKey, map));
112+
113+
Warning("InitSchemaFieldsForClass(): '%s' was not found!\n", className);
114+
return false;
115+
}
79116

80-
keyValueMap->Insert(hash_32_fnv1a_const(field.m_pszName), {field.m_nSingleInheritanceOffset, IsFieldNetworked(field)});
81-
}
117+
SchemaKeyValueMap_t& keyValueMap = tableMap.insert(std::make_pair(classKey, SchemaKeyValueMap_t())).first->second;
82118

83-
return true;
119+
InitSchemaKeyValueMap(pClassInfo, keyValueMap);
120+
121+
return true;
84122
}
85123

86-
int16_t schema::FindChainOffset(const char* className)
124+
int16_t schema::FindChainOffset(const char* className, uint32_t classNameHash)
87125
{
88-
CSchemaSystemTypeScope* pType = Interfaces::g_pSchemaSystem2->FindTypeScopeForModule(MODULE_PREFIX "server" MODULE_EXT);
126+
return schema::GetOffset(className, classNameHash, "__m_pChainEntity", g_ChainKey).offset;
127+
}
89128

90-
if (!pType)
91-
return false;
129+
SchemaKey schema::GetOffset(const char* className, uint32_t classKey, const char* memberName, uint32_t memberKey)
130+
{
131+
static SchemaTableMap_t schemaTableMap;
92132

93-
SchemaClassInfoData_t* pClassInfo = pType->FindDeclaredClass(className).Get();
133+
if (!schemaTableMap.contains(classKey))
134+
{
135+
if (InitSchemaFieldsForClass(schemaTableMap, className, classKey))
136+
return GetOffset(className, classKey, memberName, memberKey);
94137

95-
do
96-
{
97-
SchemaClassFieldData_t* pFields = pClassInfo->m_pFields;
98-
short fieldsSize = pClassInfo->m_nFieldCount;
99-
for (int i = 0; i < fieldsSize; ++i)
100-
{
101-
SchemaClassFieldData_t& field = pFields[i];
138+
return {0, 0};
139+
}
102140

103-
if (V_strcmp(field.m_pszName, "__m_pChainEntity") == 0)
104-
{
105-
return field.m_nSingleInheritanceOffset;
106-
}
107-
}
108-
} while ((pClassInfo = pClassInfo->m_pBaseClasses->m_pClass) != nullptr);
141+
SchemaKeyValueMap_t tableMap = schemaTableMap[classKey];
109142

110-
return 0;
111-
}
143+
if (!tableMap.contains(memberKey))
144+
{
145+
if (memberKey != g_ChainKey)
146+
Warning("schema::GetOffset(): '%s' was not found in '%s'!\n", memberName, className);
112147

113-
SchemaKey schema::GetOffset(const char* className, uint32_t classKey, const char* memberName, uint32_t memberKey)
114-
{
115-
static SchemaTableMap_t schemaTableMap(0, 0, DefLessFunc(uint32_t));
116-
int16_t tableMapIndex = schemaTableMap.Find(classKey);
117-
if (!schemaTableMap.IsValidIndex(tableMapIndex))
118-
{
119-
if (InitSchemaFieldsForClass(&schemaTableMap, className, classKey))
120-
return GetOffset(className, classKey, memberName, memberKey);
121-
122-
return { 0, 0 };
123-
}
124-
125-
SchemaKeyValueMap_t *tableMap = schemaTableMap[tableMapIndex];
126-
int16_t memberIndex = tableMap->Find(memberKey);
127-
if (!tableMap->IsValidIndex(memberIndex))
128-
{
129-
Warning("schema::GetOffset(): '%s' was not found in '%s'!\n", memberName, className);
130-
return { 0, 0 };
131-
}
132-
133-
return tableMap->Element(memberIndex);
148+
return {0, 0};
149+
}
150+
151+
return tableMap[memberKey];
134152
}

0 commit comments

Comments
 (0)