Начинающий
Начинающий
- Статус
- Оффлайн
- Регистрация
- 31 Июл 2025
- Сообщения
- 14
- Реакции
- 0
Hey, sorry to ask, but has anything been updated here?
schema.cpp:
#include "schema.h"
// used: [stl] vector
#include <vector>
// used: [stl] find_if
#include <algorithm>
#include "../../utils/utils.h"
// used: ischemasystem
#include "..\..\sdk\interfaces\schemasystem.h"
#include "../../helpers/log.h"
#include <Shlobj.h>
#include <shlobj_core.h>
#include "../../helpers/crt/crt.h"
#define STB_SPRINTF_IMPLEMENTATION
#include "../../helpers/sprint/stb_sprintf.h"
#include "../sdk.h"
bool GetWorkingPath(wchar_t* wszDestination)
{
const wchar_t* wszModuleName = utils::GetModuleBaseFileName(static_cast<HMODULE>(g::m_module), true);
c_run_time::StringCopy(wszDestination, wszModuleName);
// remove the module name
if (wchar_t* pwszLastSlash = c_run_time::StringCharR(wszDestination, L'\\'); pwszLastSlash != nullptr)
*pwszLastSlash = L'\0';
c_run_time::StringCat(wszDestination, L"\\WallBangBros\\");
if (!::CreateDirectoryW(wszDestination, nullptr))
{
if (const DWORD dwError = ::GetLastError(); dwError != ERROR_ALREADY_EXISTS)
{
return false;
}
}
return true;
}
struct SchemaData_t
{
uint32_t uHashedFieldName = 0x0ULL;
std::uint32_t uOffset = 0x0U;
};
static std::vector<SchemaData_t> vecSchemaData;
bool SCHEMA::Setup(const wchar_t* wszFileName, const char* szModuleName)
{
CSchemaSystemTypeScope* pTypeScope = sdk::m_schema_system->FindTypeScopeForModule(szModuleName);
if (pTypeScope == nullptr)
return false;
const int nTableSize = pTypeScope->hashClasses.Count();
// allocate memory for elements
UtlTSHashHandle_t* pElements = new UtlTSHashHandle_t[nTableSize + 1U];
const auto nElements = pTypeScope->hashClasses.GetElements(0, nTableSize, pElements);
for (int i = 0; i < nElements; i++)
{
const UtlTSHashHandle_t hElement = pElements[i];
if (hElement == 0)
continue;
CSchemaClassBinding* pClassBinding = pTypeScope->hashClasses[hElement];
if (pClassBinding == nullptr)
continue;
SchemaClassInfoData_t* pDeclaredClassInfo;
pTypeScope->FindDeclaredClass(&pDeclaredClassInfo, pClassBinding->szBinaryName);
if (pDeclaredClassInfo == nullptr)
continue;
if (pDeclaredClassInfo->nFieldSize == 0)
continue;
for (auto j = 0; j < pDeclaredClassInfo->nFieldSize; j++)
{
SchemaClassFieldData_t* pFields = pDeclaredClassInfo->pFields;
c_run_time::String_t<MAX_PATH> szFieldClassBuffer(xorstr_("%s->%s"), pClassBinding->szBinaryName, pFields[j].szName);
// store field info
vecSchemaData.emplace_back(hash_32_fnv1a_const(szFieldClassBuffer.Data()), pFields[j].nSingleInheritanceOffset);
}
#ifdef _DEBUG
CS2_LOG("dumped (name: %s total: %i) \n", pDeclaredClassInfo->szName, pDeclaredClassInfo->nFieldSize);
/*for (auto j = 0; j < pDeclaredClassInfo->nFieldSize; j++)
{
CS2_LOG("\t\tdumped (field name: %s metadata size: %i) \n", pDeclaredClassInfo->pFields[j].szName, pDeclaredClassInfo->pFields[j].nMetadataSize);
}*/
for (auto j = 0; j < pDeclaredClassInfo->nBaseClassesCount; j++)
{
CS2_LOG("\t\tdumped (name: %s) \n", pDeclaredClassInfo->pBaseClasses[j].pClass->szName);
}
#endif
}
// free allocated memory
delete[] pElements;
// close file
// ::CloseHandle(hOutFile);
return true;
}
std::uint32_t SCHEMA::GetOffset(const uint32_t uHashedFieldName)
{
if (const auto it = std::ranges::find_if(vecSchemaData, [uHashedFieldName](const SchemaData_t& data)
{ return data.uHashedFieldName == uHashedFieldName; });
it != vecSchemaData.end())
return it->uOffset;
CS2_LOG("\nfailed to find offset for field with hash: %i", uHashedFieldName);
debug(false); // schema field not found
return 0U;
}
// @todo: optimize it, can be done better
std::uint32_t SCHEMA::GetForeignOffset(const char* szModulenName, const uint32_t uHashedClassName, const uint32_t uHashedFieldName)
{
CSchemaSystemTypeScope* pTypeScope = sdk::m_schema_system->FindTypeScopeForModule(szModulenName);
if (pTypeScope == nullptr)
return false;
const int nTableSize = pTypeScope->hashClasses.Count();
// allocate memory for elements
UtlTSHashHandle_t* pElements = new UtlTSHashHandle_t[nTableSize + 1U];
const auto nElements = pTypeScope->hashClasses.GetElements(0, nTableSize, pElements);
std::uint32_t uOffset = 0x0;
for (int i = 0; i < nElements; i++)
{
const UtlTSHashHandle_t hElement = pElements[i];
if (hElement == 0)
continue;
CSchemaClassBinding* pClassBinding = pTypeScope->hashClasses[hElement];
if (pClassBinding == nullptr)
continue;
SchemaClassInfoData_t* pDeclaredClassInfo;
pTypeScope->FindDeclaredClass(&pDeclaredClassInfo, pClassBinding->szBinaryName);
if (pDeclaredClassInfo == nullptr)
continue;
if (pDeclaredClassInfo->nFieldSize == 0)
continue;
for (auto j = 0; j < pDeclaredClassInfo->nFieldSize; j++)
{
SchemaClassFieldData_t* pFields = pDeclaredClassInfo->pFields;
if (pFields == nullptr)
continue;
SchemaClassFieldData_t field = pFields[j];
if (hash_32_fnv1a_const(pClassBinding->szBinaryName) == uHashedClassName && hash_32_fnv1a_const(field.szName) == uHashedFieldName)
uOffset = field.nSingleInheritanceOffset;
}
}
return uOffset;
}
schema.h:
#pragma once
#include <memory>
#include "..\..\..\deps\fnv1a\fnv1a.h"
#define SCHEMA_ADD_OFFSET(TYPE, NAME, OFFSET) \
[[nodiscard]] inline std::add_lvalue_reference_t<TYPE> NAME() \
{ \
static const std::uint32_t uOffset = OFFSET; \
return *reinterpret_cast<std::add_pointer_t<TYPE>>(reinterpret_cast<std::uint8_t*>(this) + (uOffset)); \
}
#define SCHEMA_ADD_POFFSET(TYPE, NAME, OFFSET) \
[[nodiscard]] inline std::add_pointer_t<TYPE> NAME() \
{ \
const static std::uint32_t uOffset = OFFSET; \
return reinterpret_cast<std::add_pointer_t<TYPE>>(reinterpret_cast<std::uint8_t*>(this) + (uOffset)); \
}
#define SCHEMA_ADD_FIELD_OFFSET(TYPE, NAME, FIELD, ADDITIONAL) SCHEMA_ADD_OFFSET(TYPE, NAME, SCHEMA::GetOffset(hash_32_fnv1a_const(FIELD)) + ADDITIONAL)
#define schema(TYPE, NAME, FIELD) SCHEMA_ADD_FIELD_OFFSET(TYPE, NAME, FIELD, 0U)
#define schema2(TYPE, NAME, FIELD, ADD) SCHEMA_ADD_FIELD_OFFSET(TYPE, NAME, FIELD, ADD)
#define schema_pfield(TYPE, NAME, FIELD, ADDITIONAL) SCHEMA_ADD_POFFSET(TYPE, NAME, SCHEMA::GetOffset(hash_32_fnv1a_const(FIELD)) + ADDITIONAL)
// @todo: dump enums?
namespace SCHEMA
{
// store the offset of the field in the class
// dump stored data to file
bool Setup(const wchar_t* wszFileName, const char* szModuleName);
/* @section: get */
// get offset of the field in the class
// @note: only client.dll class & fields
[[nodiscard]] std::uint32_t GetOffset(const uint32_t uHashedFieldName);
// get foregin offset from other .dll
[[nodiscard]] std::uint32_t GetForeignOffset(const char* szModulenName, const uint32_t uHashedClassName, const uint32_t uHashedFieldName);
}