-
Notifications
You must be signed in to change notification settings - Fork 2
/
NetVarManager.cpp
216 lines (177 loc) · 5.6 KB
/
NetVarManager.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
#include "NetVars.h"
#include <fstream>
#include <utility>
#include <unordered_map>
#include "SDK.h"
//#include "XorStr.h"
using namespace std;
//------------------------------------------------------------
// Classes to help the parsing of the netvars
//------------------------------------------------------------
#pragma region Helper classes
typedef unordered_map<string, unique_ptr<NetvarTable>> TableMap;
typedef unordered_map<string, uint32_t> PropMap;
typedef unordered_map<string, unique_ptr<NetvarTable>>::iterator Iter;
struct NetvarTable
{
TableMap m_ChildTables;
PropMap m_ChildProps;
uint32_t m_uOffset = 0;
bool is_empty()
{
return m_ChildTables.size() == 0 && m_ChildProps.size() == 0;
}
void insert_table(string&& name, unique_ptr<NetvarTable>&& pTable)
{
m_ChildTables.emplace(name, std::move(pTable));
}
void insert_prop(string&& name, uint32_t offset)
{
m_ChildProps.emplace(name, offset);
}
};
class NetvarDatabase
{
public:
TableMap m_Tables;
void insert(string&& name, unique_ptr<NetvarTable>&& pTable)
{
m_Tables.emplace(name, std::move(pTable));
}
Iter find(const string& key) { return m_Tables.find(key); }
Iter begin() { return m_Tables.begin(); }
Iter end() { return m_Tables.end(); }
};
#pragma endregion
//------------------------------------------------------------
// Netvar Manager
//------------------------------------------------------------
NetvarManager* NetvarManager::instance = nullptr;
NetvarManager::NetvarManager()
{
}
NetvarManager::~NetvarManager()
{
}
void NetvarManager::CreateDatabase()
{
m_pDatabase = make_unique<NetvarDatabase>();
auto pClient = Interfaces::Client;
if (pClient) {
for (auto pClass = pClient->GetAllClasses();
pClass;
pClass = pClass->m_pNext) {
if (pClass->m_pRecvTable) {
//Insert new entry on the database
m_pDatabase->insert(
pClass->m_pRecvTable->m_pNetTableName,
InternalLoadTable(pClass->m_pRecvTable, 0));
m_tableCount++;
}
}
}
}
void NetvarManager::Dump(std::ostream& output)
{
for (auto& entry : *m_pDatabase) {
auto& pTable = entry.second;
if (pTable->is_empty())
continue;
output << entry.first << std::endl;
Dump(output, *pTable, 1);
output << "==============================================================" << std::endl;
}
}
void NetvarManager::Dump(const std::string& file)
{
std::ofstream output(file);
Dump(output);
}
//------------------------------------------------------------
// Internal methods below. This is where the real work is done
//------------------------------------------------------------
unique_ptr<NetvarTable> NetvarManager::InternalLoadTable(RecvTable* pRecvTable, uint32_t offset)
{
auto pTable = make_unique<NetvarTable>();
pTable->m_uOffset = offset;
for (auto i = 0; i < pRecvTable->m_nProps; ++i) {
auto pProp = &pRecvTable->m_pProps[i];
//Skip trash array items
if (!pProp || isdigit(pProp->m_pVarName[0])) continue;
//We dont care about the base class
if (strcmp(pProp->m_pVarName, "baseclass") == 0) continue;
//If this prop is a table
if (pProp->m_RecvType == (int)SourceEngine::SendPropType::DPT_DataTable &&
pProp->m_pDataTable != NULL && //The DataTable isnt null AND
pProp->m_pDataTable->m_pNetTableName[0] == 'D') { //The Table name starts with D (this is because there are some shitty nested
//tables that we want to skip, and those dont start with D)
//Load the table pointed by pProp->m_pDataTable and insert it
pTable->insert_table(pProp->m_pVarName, InternalLoadTable(pProp->m_pDataTable, pProp->m_Offset));
}
else {
pTable->insert_prop(pProp->m_pVarName, pProp->m_Offset);
}
m_netvarCount++;
}
return pTable;
}
void NetvarManager::Dump(std::ostream& output, NetvarTable& table, int level)
{
char line[512] = "";
char fmt[512] = "";
//yo dawg, i hear u like formatting strings so i am formatting ur formatting string
sprintf(fmt, "%%-%ds: 0x%%08X\n", 50 - level * 4);
for (auto& prop : table.m_ChildProps) {
for (int i = 0; i < level; i++) {
if (i != level - 1) {
output << " ";
}
else {
output << "|___";
}
}
sprintf(line, fmt, prop.first.c_str(), prop.second + table.m_uOffset);
output << line;
}
for (auto& child : table.m_ChildTables) {
for (int i = 0; i < level; i++) {
if (i != level - 1) {
output << " ";
}
else {
output << "|___";
}
}
sprintf(line, fmt, child.first.c_str(), child.second->m_uOffset);
output << line;
Dump(output, *child.second, level + 1);
}
}
uint32_t NetvarManager::GetOffset(const std::string& szTableName, const std::initializer_list<std::string>& props)
{
auto table = m_pDatabase->find(szTableName);
if (table == m_pDatabase->end()) return -1;
int tableOffset = table->second->m_uOffset;
if (props.size() == 0) return tableOffset;
int totalOffset = tableOffset;
NetvarTable* curTable = table->second.get();
for (auto i = 0; i < props.size(); i++) {
std::string propName = *(props.begin() + i);
if (i + 1 < props.size()) {//This index is not the last one
auto childTable = curTable->m_ChildTables.find(propName);
if (childTable == curTable->m_ChildTables.end()) {
throw std::runtime_error("Prop not found");
}
totalOffset += childTable->second->m_uOffset;
curTable = childTable->second.get();
}
else { //Last index, retrieve prop instead of table
auto childProp = curTable->m_ChildProps.find(propName);
if (childProp == curTable->m_ChildProps.end()) {
throw std::runtime_error("Prop not found");
}
totalOffset += childProp->second;
}
}
return totalOffset;
}