This commit is contained in:
Huoji's
2023-10-04 06:01:28 +08:00
parent e356220383
commit 06acf8b24d
21 changed files with 773 additions and 457 deletions

View File

@@ -87,6 +87,7 @@
"*.rh": "cpp",
"random": "cpp",
"hash_map": "cpp",
"hash_set": "cpp"
"hash_set": "cpp",
"filesystem": "cpp"
}
}

View File

@@ -230,6 +230,7 @@
<ClInclude Include="sdk\tier1\UtlVector.hpp" />
<ClInclude Include="sdk_tools.h" />
<ClInclude Include="stb.hh" />
<ClInclude Include="timer.h" />
<ClInclude Include="tools.h" />
<ClInclude Include="vector.h" />
<ClInclude Include="vmt.h" />
@@ -297,6 +298,7 @@
<ClCompile Include="sdk\convar\convar.cpp" />
<ClCompile Include="sdk\tier1\UtlString.cpp" />
<ClCompile Include="sdk_tools.cpp" />
<ClCompile Include="timer.cpp" />
<ClCompile Include="tools.cpp" />
<ClCompile Include="vmthook.cpp" />
</ItemGroup>

View File

@@ -76,6 +76,12 @@
<Filter Include="头文件\lua">
<UniqueIdentifier>{d58fcaf6-b1d7-484d-9ec4-d6b67ff46cf5}</UniqueIdentifier>
</Filter>
<Filter Include="源文件\game_time_system">
<UniqueIdentifier>{ccc753a5-6730-455d-b12b-9fa7e9a4cf03}</UniqueIdentifier>
</Filter>
<Filter Include="头文件\game_time_system">
<UniqueIdentifier>{f26913ae-881a-43da-a215-8c0c7a9173cd}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<ClInclude Include="framework.h">
@@ -318,6 +324,9 @@
<ClInclude Include="vector.h">
<Filter>头文件\native_sdk</Filter>
</ClInclude>
<ClInclude Include="timer.h">
<Filter>头文件\game_time_system</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="dllmain.cpp">
@@ -491,6 +500,9 @@
<ClCompile Include="script_callbacks.cpp">
<Filter>源文件\script_engine</Filter>
</ClCompile>
<ClCompile Include="timer.cpp">
<Filter>源文件\game_time_system</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<None Include="cpp.hint" />

View File

@@ -28,7 +28,8 @@ auto OnPlayerDeathEvent(IGameEvent* event) -> void {
}
const auto victimIndex = victim->GetRefEHandle().GetEntryIndex();
const auto attackerIndex = attacker->GetRefEHandle().GetEntryIndex();
ScriptCallBacks::luaCall_onPlayerDeath(victimIndex, attackerIndex, isHeadShot);
ScriptCallBacks::luaCall_onPlayerDeath(victimIndex, attackerIndex,
isHeadShot);
// printf("player[%p] %s kill[%p] %llu\n", attacker,
// &attacker->m_iszPlayerName(), victim, &victim->m_steamID());
}
@@ -38,10 +39,8 @@ auto OnPlayerChat(CCSPlayerController* player, std::string message) -> bool {
if (procesChatSuccess == false) {
return false;
}
if (chatCtx.at(0) == '/' || chatCtx.at(0) == '!') {
return true;
}
return false;
return ScriptCallBacks::luaCall_onPlayerSpeak(
player->GetRefEHandle().GetEntryIndex(), chatType, chatCtx);
}
auto OnPlayerConnect(int slot, const char* pszName, uint64_t xuid,
const char* pszNetworkID, const char* pszAddress,

View File

@@ -2,4 +2,9 @@
namespace global {
bool Exit;
int MaxPlayers;
CGameEntitySystem* EntitySystem;
bool HasTicked;
CGlobalVars* GlobalVars;
float m_flUniversalTime;
float m_flLastTickedTime;
}

View File

@@ -1,6 +1,13 @@
#pragma once
#include "head.h"
class CGlobalVars;
class CGameEntitySystem;
namespace global {
extern bool Exit;
extern int MaxPlayers;
extern CGameEntitySystem* EntitySystem;
extern bool HasTicked;
extern CGlobalVars* GlobalVars;
extern float m_flUniversalTime;
extern float m_flLastTickedTime;
}

View File

@@ -79,3 +79,4 @@ static void DebugPrintA(const char* format, ...) {
#include "script_engine.h"
#include "script_apis.h"
#include "script_callbacks.h"
#include "timer.h"

View File

@@ -1,13 +1,58 @@
#include "hooks.h"
extern auto GetGameGlobals() -> CGlobalVars*;
FireEventServerSide_t original_FireEventServerSide = NULL;
OnClientConnect_t original_OnClientConnected = NULL;
OnClientDisconnect_t original_OnClientDisconnect = NULL;
Host_Say_t original_Host_Say = NULL;
StartupServer_t origin_StartServer = NULL;
GameFrame_t origin_GameFrame = NULL;
namespace hooks {
// "player_connect"
VMTHook* VMT_IServerGameClient;
VMTHook* VMT_INetworkServerServiceInteFace;
VMTHook* VMT_ISource2ServerInterFace;
void __fastcall hook_GameFrame(void* rcx, bool simulating, bool bFirstTick,
bool bLastTick) {
/**
* simulating:
* ***********
* true | game is ticking
* false | game is not ticking
*/
if (simulating && global::HasTicked) {
global::m_flUniversalTime +=
global::GlobalVars->curtime - global::m_flLastTickedTime;
} else {
global::m_flUniversalTime += global::GlobalVars->interval_per_tick;
}
global::m_flLastTickedTime = global::GlobalVars->curtime;
global::HasTicked = true;
if (global::EntitySystem == nullptr) {
global::EntitySystem = Offset::InterFaces::GameResourceServiceServer
->GetGameEntitySystem();
}
GameTimer::ExcuteTimers();
return origin_GameFrame(rcx, simulating, bFirstTick, bLastTick);
}
void __fastcall hook_StartServer(void* rcx,
const GameSessionConfiguration_t& config,
ISource2WorldSession* pWorldSession,
const char* a1) {
if (global::HasTicked) {
GameTimer::CleanUpTimers();
}
global::HasTicked = false;
global::GlobalVars = GetGameGlobals();
global::EntitySystem =
Offset::InterFaces::GameResourceServiceServer->GetGameEntitySystem();
return origin_StartServer(rcx, config, pWorldSession, a1);
}
void __fastcall hook_ClientDisconnect(void* rcx, CPlayerSlot slot, int reason,
const char* pszName, uint64_t xuid,
const char* pszNetworkID) {
@@ -134,11 +179,24 @@ auto initMinHook() -> bool {
auto initVmtHook() -> bool {
VMT_IServerGameClient = new VMTHook(Memory::read<void*>(
reinterpret_cast<uint64_t>(Offset::InterFaces::IServerGameClient)));
VMT_INetworkServerServiceInteFace =
new VMTHook(Memory::read<void*>(reinterpret_cast<uint64_t>(
Offset::InterFaces::INetworkServerServiceInteFace)));
VMT_ISource2ServerInterFace =
new VMTHook(Memory::read<void*>(reinterpret_cast<uint64_t>(
Offset::InterFaces::ISource2ServerInterFace)));
original_OnClientConnected = reinterpret_cast<OnClientConnect_t>(
VMT_IServerGameClient->Hook(11, hook_OnClientConnected));
original_OnClientDisconnect = reinterpret_cast<OnClientDisconnect_t>(
VMT_IServerGameClient->Hook(16, hook_ClientDisconnect));
return original_OnClientConnected && original_OnClientDisconnect;
origin_StartServer = reinterpret_cast<StartupServer_t>(
VMT_INetworkServerServiceInteFace->Hook(27, hook_StartServer));
origin_GameFrame = reinterpret_cast<GameFrame_t>(
VMT_ISource2ServerInterFace->Hook(19, hook_GameFrame));
return original_OnClientConnected && original_OnClientDisconnect &&
origin_StartServer && origin_GameFrame;
}
auto init() -> bool {
bool isSuccess = initMinHook() && initVmtHook();

View File

@@ -5,6 +5,8 @@ typedef bool(__fastcall* FireEventServerSide_t)(CGameEventManager*, IGameEvent*,
typedef void(__fastcall* Host_Say_t)(void*, void*, bool, int, const char*);
typedef void(__fastcall* OnClientConnect_t)(void*, CPlayerSlot, const char*, uint64_t, const char*, const char*, bool);
typedef void(__fastcall* OnClientDisconnect_t)(void*, CPlayerSlot, int, const char*, uint64_t, const char*);
typedef void(__fastcall* StartupServer_t)(void*, const GameSessionConfiguration_t&, ISource2WorldSession*, const char*);
typedef void(__fastcall* GameFrame_t)(void*, bool, bool, bool);
extern FireEventServerSide_t original_FireEventServerSide;
extern Host_Say_t original_Host_Say;

View File

@@ -1,10 +1,8 @@
#include "native_sdk.h"
CBaseEntity* CHandle::GetBaseEntity() const
{
CBaseEntity* CHandle::GetBaseEntity() const {
CGameEntitySystem* pEntitySystem = CGameEntitySystem::GetInstance();
if (!pEntitySystem)
return nullptr;
if (!pEntitySystem) return nullptr;
return pEntitySystem->GetBaseEntity(GetEntryIndex());
}
@@ -12,29 +10,27 @@ CGameEntitySystem* CGameEntitySystem::GetInstance() {
return Offset::InterFaces::GameResourceServiceServer->GetGameEntitySystem();
}
auto CSchemaSystemTypeScope::FindDeclaredClass(const char* pClass) -> SchemaClassInfoData_t*
{
auto CSchemaSystemTypeScope::FindDeclaredClass(const char* pClass)
-> SchemaClassInfoData_t* {
SchemaClassInfoData_t* rv = nullptr;
CALL_VIRTUAL(void, 2, this, &rv, pClass);
return rv;
}
auto CSchemaSystem::FindTypeScopeForModule(const char* module) -> CSchemaSystemTypeScope*
{
auto CSchemaSystem::FindTypeScopeForModule(const char* module)
-> CSchemaSystemTypeScope* {
return CALL_VIRTUAL(CSchemaSystemTypeScope*, 13, this, module, nullptr);
}
bool CBaseEntity::IsBasePlayerController() {
auto CBaseEntity::IsBasePlayerController() -> bool {
return CALL_VIRTUAL(bool, 144, this);
}
auto CBasePlayer::ForceRespawn() -> void
{
auto CBaseEntity::SpawnClientEntity() -> void { CALL_VIRTUAL(void, 19, this); }
auto CBasePlayer::ForceRespawn() -> void {
return CALL_VIRTUAL(void, 26, this);
}
auto CCSPlayerPawn::GetPlayerController() -> CCSPlayerController*
{
auto CCSPlayerPawn::GetPlayerController() -> CCSPlayerController* {
CGameEntitySystem* pEntitySystem = CGameEntitySystem::GetInstance();
if (!pEntitySystem) {
return nullptr;
@@ -45,7 +41,9 @@ auto CCSPlayerPawn::GetPlayerController() -> CCSPlayerController*
if (pEntity->IsBasePlayerController()) {
const auto player = reinterpret_cast<CCSPlayerController*>(pEntity);
if (player->m_hPawn().Get() == this) {
//printf("Found Pawn Player: %d %s \n", player->GetRefEHandle().GetEntryIndex(), &player->m_iszPlayerName());
// printf("Found Pawn Player: %d %s \n",
// player->GetRefEHandle().GetEntryIndex(),
// &player->m_iszPlayerName());
return player;
}
}
@@ -56,11 +54,8 @@ auto CCSPlayerPawn::GetPlayerController() -> CCSPlayerController*
using SchemaKeyValueMap_t = CUtlMap<uint32_t, SchemaKey>;
using SchemaTableMap_t = CUtlMap<uint32_t, SchemaKeyValueMap_t*>;
static bool IsFieldNetworked(SchemaClassFieldData_t& field)
{
for (int i = 0; i < field.m_metadata_size; i++)
{
static bool IsFieldNetworked(SchemaClassFieldData_t& field) {
for (int i = 0; i < field.m_metadata_size; i++) {
static auto networkEnabled = hash_32_fnv1a_const("MNetworkEnable");
if (networkEnabled == hash_32_fnv1a_const(field.m_metadata[i].m_name))
return true;
@@ -69,18 +64,18 @@ static bool IsFieldNetworked(SchemaClassFieldData_t& field)
return false;
}
static bool InitSchemaFieldsForClass(SchemaTableMap_t* tableMap, const char* className, uint32_t classKey)
{
CSchemaSystemTypeScope* pType = Offset::InterFaces::SchemaSystem->FindTypeScopeForModule("server.dll");
static bool InitSchemaFieldsForClass(SchemaTableMap_t* tableMap,
const char* className, uint32_t classKey) {
CSchemaSystemTypeScope* pType =
Offset::InterFaces::SchemaSystem->FindTypeScopeForModule("server.dll");
if (!pType)
return false;
if (!pType) return false;
SchemaClassInfoData_t* pClassInfo = pType->FindDeclaredClass(className);
if (!pClassInfo)
{
SchemaKeyValueMap_t* map = new SchemaKeyValueMap_t(0, 0, DefLessFunc(uint32_t));
if (!pClassInfo) {
SchemaKeyValueMap_t* map =
new SchemaKeyValueMap_t(0, 0, DefLessFunc(uint32_t));
tableMap->Insert(classKey, map);
LOG("InitSchemaFieldsForClass(): '%s' was not found!\n", className);
@@ -90,40 +85,38 @@ static bool InitSchemaFieldsForClass(SchemaTableMap_t* tableMap, const char* cla
short fieldsSize = pClassInfo->GetFieldsSize();
SchemaClassFieldData_t* pFields = pClassInfo->GetFields();
SchemaKeyValueMap_t* keyValueMap = new SchemaKeyValueMap_t(0, 0, DefLessFunc(uint32_t));
SchemaKeyValueMap_t* keyValueMap =
new SchemaKeyValueMap_t(0, 0, DefLessFunc(uint32_t));
keyValueMap->EnsureCapacity(fieldsSize);
tableMap->Insert(classKey, keyValueMap);
for (int i = 0; i < fieldsSize; ++i)
{
for (int i = 0; i < fieldsSize; ++i) {
SchemaClassFieldData_t& field = pFields[i];
// LOG("%s::%s found at -> 0x%X - %llx\n", className, field.m_name,
// field.m_offset, &field);
keyValueMap->Insert(hash_32_fnv1a_const(field.m_name), { field.m_offset, IsFieldNetworked(field) });
keyValueMap->Insert(hash_32_fnv1a_const(field.m_name),
{field.m_offset, IsFieldNetworked(field)});
}
return true;
}
int16_t schema::FindChainOffset(const char* className)
{
CSchemaSystemTypeScope* pType = Offset::InterFaces::SchemaSystem->FindTypeScopeForModule("server.dll");
int16_t schema::FindChainOffset(const char* className) {
CSchemaSystemTypeScope* pType =
Offset::InterFaces::SchemaSystem->FindTypeScopeForModule("server.dll");
if (!pType)
return false;
if (!pType) return false;
SchemaClassInfoData_t* pClassInfo = pType->FindDeclaredClass(className);
do
{
do {
SchemaClassFieldData_t* pFields = pClassInfo->GetFields();
short fieldsSize = pClassInfo->GetFieldsSize();
for (int i = 0; i < fieldsSize; ++i)
{
for (int i = 0; i < fieldsSize; ++i) {
SchemaClassFieldData_t& field = pFields[i];
if (strcmp(field.m_name, "__m_pChainEntity") == 0)
{
if (strcmp(field.m_name, "__m_pChainEntity") == 0) {
return field.m_offset;
}
}
@@ -132,24 +125,23 @@ int16_t schema::FindChainOffset(const char* className)
return 0;
}
SchemaKey schema::GetOffset(const char* className, uint32_t classKey, const char* memberName, uint32_t memberKey)
{
SchemaKey schema::GetOffset(const char* className, uint32_t classKey,
const char* memberName, uint32_t memberKey) {
static SchemaTableMap_t schemaTableMap(0, 0, DefLessFunc(uint32_t));
int16_t tableMapIndex = schemaTableMap.Find(classKey);
if (!schemaTableMap.IsValidIndex(tableMapIndex))
{
if (!schemaTableMap.IsValidIndex(tableMapIndex)) {
if (InitSchemaFieldsForClass(&schemaTableMap, className, classKey))
return GetOffset(className, classKey, memberName, memberKey);
return { 0, 0 };
return {0, 0};
}
SchemaKeyValueMap_t* tableMap = schemaTableMap[tableMapIndex];
int16_t memberIndex = tableMap->Find(memberKey);
if (!tableMap->IsValidIndex(memberIndex))
{
LOG("schema::GetOffset(): '%s' was not found in '%s'!\n", memberName, className);
return { 0, 0 };
if (!tableMap->IsValidIndex(memberIndex)) {
LOG("schema::GetOffset(): '%s' was not found in '%s'!\n", memberName,
className);
return {0, 0};
}
return tableMap->Element(memberIndex);
@@ -177,27 +169,26 @@ bool CEconItemDefinition::IsGlove(bool excludeDefault) {
return excludeDefault ? !defaultGlove : true;
}
auto CLocalize::FindSafe(const char* tokenName) -> const char*
{
auto CLocalize::FindSafe(const char* tokenName) -> const char* {
return CALL_VIRTUAL(const char*, 17, this, tokenName);
}
auto GetGameGlobals() -> CGlobalVars*
{
INetworkGameServer* server = Offset::InterFaces::INetworkServerServiceInteFace->GetIGameServer();
auto GetGameGlobals() -> CGlobalVars* {
INetworkGameServer* server =
Offset::InterFaces::INetworkServerServiceInteFace->GetIGameServer();
if (!server)
return nullptr;
if (!server) return nullptr;
return Offset::InterFaces::INetworkServerServiceInteFace->GetIGameServer()->GetGlobals();
return Offset::InterFaces::INetworkServerServiceInteFace->GetIGameServer()
->GetGlobals();
}
auto SetStateChanged(Z_CBaseEntity* pEntity, int offset) -> void
{
Offset::FnStateChanged(pEntity->m_NetworkTransmitComponent(), pEntity, offset, -1, -1);
auto vars = GetGameGlobals();
auto SetStateChanged(Z_CBaseEntity* pEntity, int offset) -> void {
Offset::FnStateChanged(pEntity->m_NetworkTransmitComponent(), pEntity,
offset, -1, -1);
// auto vars = GetGameGlobals();
auto vars = global::GlobalVars;
if (vars)
pEntity->m_lastNetworkChange(vars->curtime);
if (vars) pEntity->m_lastNetworkChange(vars->curtime);
pEntity->m_isSteadyState(0);
};

View File

@@ -1,313 +1,287 @@
#pragma once
#include "head.h"
class CEntityInstance;
typedef void(__fastcall* StateChanged_t)(void* networkTransmitComponent, CEntityInstance* ent, uint64_t offset, int a4, int a5);
typedef void(__fastcall* NetworkStateChanged_t)(uintptr_t chainEntity, uintptr_t offset, uintptr_t a3);
typedef void(__fastcall* StateChanged_t)(void* networkTransmitComponent,
CEntityInstance* ent, uint64_t offset,
int a4, int a5);
typedef void(__fastcall* NetworkStateChanged_t)(uintptr_t chainEntity,
uintptr_t offset, uintptr_t a3);
namespace Offset {
extern StateChanged_t FnStateChanged;
extern NetworkStateChanged_t FnNetworkStateChanged;
}
extern StateChanged_t FnStateChanged;
extern NetworkStateChanged_t FnNetworkStateChanged;
} // namespace Offset
struct SchemaKey {
int16_t offset;
bool networked;
int16_t offset;
bool networked;
};
class Z_CBaseEntity;
extern auto SetStateChanged(Z_CBaseEntity* pEntity, int offset) -> void;
#define MAX_ENTITIES_IN_LIST 512
#define MAX_ENTITY_LISTS 64
#define MAX_TOTAL_ENTITIES MAX_ENTITIES_IN_LIST *MAX_ENTITY_LISTS
#define MAX_ENTITY_LISTS 64
#define MAX_TOTAL_ENTITIES MAX_ENTITIES_IN_LIST* MAX_ENTITY_LISTS
#define INVALID_EHANDLE_INDEX 0xFFFFFFFF
#define ENT_ENTRY_MASK 0x7FFF
#define ENT_ENTRY_MASK 0x7FFF
#define DECLARE_SCHEMA_CLASS_BASE(className, isStruct) \
static constexpr const char *ThisClass = #className; \
static constexpr bool OffsetIsStruct = isStruct;
#define DECLARE_SCHEMA_CLASS_BASE(className, isStruct) \
static constexpr const char* ThisClass = #className; \
static constexpr bool OffsetIsStruct = isStruct;
#define DECLARE_CLASS(className) DECLARE_SCHEMA_CLASS_BASE(className, false)
// Use this for classes that can be wholly included within other classes (like CCollisionProperty within CBaseModelEntity)
// Use this for classes that can be wholly included within other classes (like
// CCollisionProperty within CBaseModelEntity)
#define DECLARE_SCHEMA_CLASS_INLINE(className) \
DECLARE_SCHEMA_CLASS_BASE(className, true)
DECLARE_SCHEMA_CLASS_BASE(className, true)
#define SCHEMA_FIELD_OFFSET(type, varName, extra_offset) \
std::add_lvalue_reference_t<type> varName() \
{ \
static constexpr auto datatable_hash = hash_32_fnv1a_const(ThisClass); \
static constexpr auto prop_hash = hash_32_fnv1a_const(#varName); \
\
static const auto m_key = \
schema::GetOffset(ThisClass, datatable_hash, #varName, prop_hash); \
\
return *reinterpret_cast<std::add_pointer_t<type>>( \
(uintptr_t)(this) + m_key.offset + extra_offset); \
} \
void varName(type val) \
{ \
static constexpr auto datatable_hash = hash_32_fnv1a_const(ThisClass); \
static constexpr auto prop_hash = hash_32_fnv1a_const(#varName); \
\
static const auto m_key = \
schema::GetOffset(ThisClass, datatable_hash, #varName, prop_hash); \
\
static const auto m_chain = \
schema::FindChainOffset(ThisClass); \
\
if (m_chain != 0 && m_key.networked) \
{ \
LOG("Found chain offset %d for %s::%s\n", m_chain, ThisClass, #varName); \
Offset::FnNetworkStateChanged((uintptr_t)(this) + m_chain, m_key.offset + extra_offset, 0xFFFFFFFF); \
} \
else if(m_key.networked) \
{ \
/* WIP: Works fine for most props, but inlined classes in the middle of a class will
need to have their this pointer corrected by the offset .*/ \
LOG("Attempting to call SetStateChanged on on %s::%s\n", ThisClass, #varName); \
if (!OffsetIsStruct) \
SetStateChanged((Z_CBaseEntity*)this, m_key.offset + extra_offset); \
else \
CALL_VIRTUAL(void, 1, this, m_key.offset + extra_offset, 0xFFFFFFFF, 0xFFFF); \
\
} \
* reinterpret_cast<std::add_pointer_t<type>>((uintptr_t)(this) + m_key.offset + extra_offset) = val; \
}
#define SCHEMA_FIELD_OFFSET(type, varName, extra_offset) \
std::add_lvalue_reference_t<type> varName() { \
static constexpr auto datatable_hash = hash_32_fnv1a_const(ThisClass); \
static constexpr auto prop_hash = hash_32_fnv1a_const(#varName); \
\
static const auto m_key = \
schema::GetOffset(ThisClass, datatable_hash, #varName, prop_hash); \
\
return *reinterpret_cast<std::add_pointer_t<type>>( \
(uintptr_t)(this) + m_key.offset + extra_offset); \
} \
void varName(type val) { \
static constexpr auto datatable_hash = hash_32_fnv1a_const(ThisClass); \
static constexpr auto prop_hash = hash_32_fnv1a_const(#varName); \
\
static const auto m_key = \
schema::GetOffset(ThisClass, datatable_hash, #varName, prop_hash); \
\
static const auto m_chain = schema::FindChainOffset(ThisClass); \
\
if (m_chain != 0 && m_key.networked) { \
LOG("Found chain offset %d for %s::%s\n", m_chain, ThisClass, \
#varName); \
Offset::FnNetworkStateChanged((uintptr_t)(this) + m_chain, \
m_key.offset + extra_offset, \
0xFFFFFFFF); \
} else if (m_key.networked) { \
/* WIP: Works fine for most props, but inlined classes in the \
middle of a class will need to have their this pointer \
corrected by the offset .*/ \
LOG("Attempting to call SetStateChanged on on %s::%s\n", \
ThisClass, #varName); \
if (!OffsetIsStruct) \
SetStateChanged((Z_CBaseEntity*)this, \
m_key.offset + extra_offset); \
else \
CALL_VIRTUAL(void, 1, this, m_key.offset + extra_offset, \
0xFFFFFFFF, 0xFFFF); \
} \
*reinterpret_cast<std::add_pointer_t<type>>( \
(uintptr_t)(this) + m_key.offset + extra_offset) = val; \
}
#define SCHEMA_FIELD(type, varName) \
SCHEMA_FIELD_OFFSET(type, varName, 0)
#define SCHEMA_FIELD(type, varName) SCHEMA_FIELD_OFFSET(type, varName, 0)
#define PSCHEMA_FIELD_OFFSET(type, varName, extra_offset) \
auto varName() { \
static constexpr auto datatable_hash = hash_32_fnv1a_const(ThisClass); \
static constexpr auto prop_hash = hash_32_fnv1a_const(#varName); \
\
static const auto m_key = \
schema::GetOffset(ThisClass, datatable_hash, #varName, prop_hash); \
\
return reinterpret_cast<std::add_pointer_t<type>>( \
(uintptr_t)(this) + m_key.offset + extra_offset); \
}
#define PSCHEMA_FIELD_OFFSET(type, varName, extra_offset) \
auto varName() \
{ \
static constexpr auto datatable_hash = hash_32_fnv1a_const(ThisClass); \
static constexpr auto prop_hash = hash_32_fnv1a_const(#varName); \
\
static const auto m_key = \
schema::GetOffset(ThisClass, datatable_hash, #varName, prop_hash); \
\
return reinterpret_cast<std::add_pointer_t<type>>( \
(uintptr_t)(this) + m_key.offset + extra_offset); \
}
#define PSCHEMA_FIELD(type, varName) PSCHEMA_FIELD_OFFSET(type, varName, 0)
#define PSCHEMA_FIELD(type, varName) \
PSCHEMA_FIELD_OFFSET(type, varName, 0)
namespace schema
{
int16_t FindChainOffset(const char* className);
SchemaKey GetOffset(const char* className, uint32_t classKey, const char* memberName, uint32_t memberKey);
}
namespace schema {
int16_t FindChainOffset(const char* className);
SchemaKey GetOffset(const char* className, uint32_t classKey,
const char* memberName, uint32_t memberKey);
} // namespace schema
struct CSchemaNetworkValue {
union {
const char* m_sz_value;
int m_n_value;
float m_f_value;
std::uintptr_t m_p_value;
};
union {
const char* m_sz_value;
int m_n_value;
float m_f_value;
std::uintptr_t m_p_value;
};
};
struct SchemaMetadataEntryData_t {
const char* m_name;
CSchemaNetworkValue* m_value;
const char* m_name;
CSchemaNetworkValue* m_value;
};
struct SchemaClassFieldData_t
{
const char* m_name;
char pad0[0x8];
short m_offset;
int32_t m_metadata_size;
SchemaMetadataEntryData_t* m_metadata;
struct SchemaClassFieldData_t {
const char* m_name;
char pad0[0x8];
short m_offset;
int32_t m_metadata_size;
SchemaMetadataEntryData_t* m_metadata;
};
class SchemaClassInfoData_t;
struct SchemaBaseClassInfoData_t
{
unsigned int m_offset;
SchemaClassInfoData_t* m_class;
struct SchemaBaseClassInfoData_t {
unsigned int m_offset;
SchemaClassInfoData_t* m_class;
};
class SchemaClassInfoData_t
{
public:
auto GetName()
{
return m_name;
}
class SchemaClassInfoData_t {
public:
auto GetName() { return m_name; }
auto GetFieldsSize()
{
return m_align;
}
auto GetFieldsSize() { return m_align; }
auto GetFields()
{
return m_fields;
}
auto GetFields() { return m_fields; }
auto GetParent() -> SchemaClassInfoData_t*
{
if (!m_schema_parent)
return nullptr;
auto GetParent() -> SchemaClassInfoData_t* {
if (!m_schema_parent) return nullptr;
return m_schema_parent->m_class;
}
return m_schema_parent->m_class;
}
private:
char pad_0x0000[0x8]; // 0x0000
private:
char pad_0x0000[0x8]; // 0x0000
const char* m_name; // 0x0008
char* m_module; // 0x0010
const char* m_name; // 0x0008
char* m_module; // 0x0010
int m_size; // 0x0018
std::int16_t m_align; // 0x001C
int m_size; // 0x0018
std::int16_t m_align; // 0x001C
std::int16_t m_static_size; // 0x001E
std::int16_t m_metadata_size; // 0x0020
std::int16_t m_i_unk1; // 0x0022
std::int16_t m_i_unk2; // 0x0024
std::int16_t m_i_unk3; // 0x0026
std::int16_t m_static_size; // 0x001E
std::int16_t m_metadata_size; // 0x0020
std::int16_t m_i_unk1; // 0x0022
std::int16_t m_i_unk2; // 0x0024
std::int16_t m_i_unk3; // 0x0026
SchemaClassFieldData_t* m_fields; // 0x0028
SchemaClassFieldData_t* m_fields; // 0x0028
char pad_0x0030[0x8]; // 0x0030
SchemaBaseClassInfoData_t* m_schema_parent; // 0x0038
char pad_0x0030[0x8]; // 0x0030
SchemaBaseClassInfoData_t* m_schema_parent; // 0x0038
char pad_0x0038[0x10]; // 0x0038
char pad_0x0038[0x10]; // 0x0038
};
class CSchemaSystemTypeScope
{
public:
auto FindDeclaredClass(const char* pClass) -> SchemaClassInfoData_t*;
class CSchemaSystemTypeScope {
public:
auto FindDeclaredClass(const char* pClass) -> SchemaClassInfoData_t*;
};
class CSchemaSystem
{
public:
auto FindTypeScopeForModule(const char* module) -> CSchemaSystemTypeScope*;
class CSchemaSystem {
public:
auto FindTypeScopeForModule(const char* module) -> CSchemaSystemTypeScope*;
};
template <typename T>
class CUtlVector_NativeSdk {
public:
auto begin() const { return m_data; }
auto end() const { return m_data + m_size; }
public:
auto begin() const { return m_data; }
auto end() const { return m_data + m_size; }
bool Exists(T val) const {
for (const auto& it : *this)
if (it == val) return true;
return false;
}
bool Empty() const { return m_size == 0; }
bool Exists(T val) const {
for (const auto& it : *this)
if (it == val) return true;
return false;
}
bool Empty() const { return m_size == 0; }
int m_size;
char pad0[0x4]; // no idea
T* m_data;
char pad1[0x8]; // no idea
int m_size;
char pad0[0x4]; // no idea
T* m_data;
char pad1[0x8]; // no idea
};
class CBaseEntity;
class CEntityIdentity
{
public:
CBaseEntity* entity; //0
void* dunno; //8
int64_t unk0; //12
int64_t unk1; //16
const char* internalName;
const char* entityName;
void* unk2;
void* unk3;
void* unk4;
void* unk5;
CEntityIdentity* prevValid;
CEntityIdentity* nextValid;
void* unkptr;
void* unkptr2;
void* unkptr3;
class CEntityIdentity {
public:
CBaseEntity* entity; // 0
void* dunno; // 8
int64_t unk0; // 12
int64_t unk1; // 16
const char* internalName;
const char* entityName;
void* unk2;
void* unk3;
void* unk4;
void* unk5;
CEntityIdentity* prevValid;
CEntityIdentity* nextValid;
void* unkptr;
void* unkptr2;
void* unkptr3;
};
class CEntityIdentities
{
public:
CEntityIdentity m_pIdentities[MAX_ENTITIES_IN_LIST];
class CEntityIdentities {
public:
CEntityIdentity m_pIdentities[MAX_ENTITIES_IN_LIST];
};
class EntityIdentityList
{
public:
CEntityIdentities* m_pIdentityList;
class EntityIdentityList {
public:
CEntityIdentities* m_pIdentityList;
};
class CGameEntitySystem
{
public:
virtual void n_0();
void* unk;
CEntityIdentities* m_pEntityList[MAX_ENTITY_LISTS];
class CGameEntitySystem {
public:
virtual void n_0();
void* unk;
CEntityIdentities* m_pEntityList[MAX_ENTITY_LISTS];
CBaseEntity* GetBaseEntity(int index)
{
if (index <= -1 || index >= MAX_TOTAL_ENTITIES)
return nullptr;
CBaseEntity* GetBaseEntity(int index) {
if (index <= -1 || index >= MAX_TOTAL_ENTITIES) return nullptr;
int listToUse = (index / MAX_ENTITIES_IN_LIST);
if (!m_pEntityList[listToUse])
return nullptr;
int listToUse = (index / MAX_ENTITIES_IN_LIST);
if (!m_pEntityList[listToUse]) return nullptr;
if (m_pEntityList[listToUse]->m_pIdentities[index % MAX_ENTITIES_IN_LIST].entity)
return m_pEntityList[listToUse]->m_pIdentities[index % MAX_ENTITIES_IN_LIST].entity;
else
return nullptr;
}
if (m_pEntityList[listToUse]
->m_pIdentities[index % MAX_ENTITIES_IN_LIST]
.entity)
return m_pEntityList[listToUse]
->m_pIdentities[index % MAX_ENTITIES_IN_LIST]
.entity;
else
return nullptr;
}
static CGameEntitySystem* GetInstance();
static CGameEntitySystem* GetInstance();
};
struct VPhysicsCollisionAttribute_t
{
DECLARE_CLASS(VPhysicsCollisionAttribute_t)
struct VPhysicsCollisionAttribute_t {
DECLARE_CLASS(VPhysicsCollisionAttribute_t)
SCHEMA_FIELD(uint8_t, m_nCollisionGroup)
SCHEMA_FIELD(uint8_t, m_nCollisionGroup)
};
class CCollisionProperty
{
public:
DECLARE_CLASS(CCollisionProperty)
class CCollisionProperty {
public:
DECLARE_CLASS(CCollisionProperty)
SCHEMA_FIELD(VPhysicsCollisionAttribute_t, m_collisionAttribute)
//SCHEMA_FIELD(SolidType_t, m_nSolidType)
SCHEMA_FIELD(uint8_t, m_usSolidFlags)
SCHEMA_FIELD(uint8_t, m_CollisionGroup)
SCHEMA_FIELD(VPhysicsCollisionAttribute_t, m_collisionAttribute)
// SCHEMA_FIELD(SolidType_t, m_nSolidType)
SCHEMA_FIELD(uint8_t, m_usSolidFlags)
SCHEMA_FIELD(uint8_t, m_CollisionGroup)
};
class CHandle
{
CBaseEntity* GetBaseEntity() const;
class CHandle {
CBaseEntity* GetBaseEntity() const;
public:
bool operator==(CHandle rhs) const { return m_Index == rhs.m_Index; }
public:
bool operator==(CHandle rhs) const { return m_Index == rhs.m_Index; }
bool IsValid() const { return m_Index != INVALID_EHANDLE_INDEX; }
bool IsValid() const { return m_Index != INVALID_EHANDLE_INDEX; }
int GetEntryIndex() const { return m_Index & ENT_ENTRY_MASK; }
int GetEntryIndex() const { return m_Index & ENT_ENTRY_MASK; }
template <typename T = CBaseEntity>
T* Get() const
{
return reinterpret_cast<T*>(GetBaseEntity());
}
uint32_t m_Index;
template <typename T = CBaseEntity>
T* Get() const {
return reinterpret_cast<T*>(GetBaseEntity());
}
uint32_t m_Index;
};
class CEntityInstance {
public:
public:
DECLARE_CLASS(CEntityInstance);
auto Schema_DynamicBinding() {
@@ -333,18 +307,19 @@ public:
};
class CBaseEntity : public CEntityInstance {
public:
public:
DECLARE_CLASS(CBaseEntity);
SCHEMA_FIELD(int, m_iHealth)
SCHEMA_FIELD(int, m_iTeamNum)
// SCHEMA_FIELD(Vector, m_vecBaseVelocity)
SCHEMA_FIELD(CCollisionProperty*, m_pCollision)
bool IsBasePlayerController();
auto IsBasePlayerController() -> bool;
auto SpawnClientEntity() -> void;
};
class CBasePlayerController : public CBaseEntity {
public:
public:
DECLARE_CLASS(CBasePlayerController);
SCHEMA_FIELD(uint64_t, m_steamID)
@@ -354,7 +329,7 @@ public:
};
class CCSPlayerController : public CBasePlayerController {
public:
public:
DECLARE_CLASS(CCSPlayerController)
SCHEMA_FIELD(uint32_t, m_iPawnHealth)
@@ -363,159 +338,157 @@ public:
};
class CEconItemDefinition {
public:
bool IsWeapon();
bool IsKnife(bool excludeDefault);
bool IsGlove(bool excludeDefault);
public:
bool IsWeapon();
bool IsKnife(bool excludeDefault);
bool IsGlove(bool excludeDefault);
auto GetModelName() {
return *reinterpret_cast<const char**>((uintptr_t)(this) + 0xD8);
}
auto GetModelName() {
return *reinterpret_cast<const char**>((uintptr_t)(this) + 0xD8);
}
auto GetStickersSupportedCount() {
return *reinterpret_cast<int*>((uintptr_t)(this) + 0x100);
}
auto GetStickersSupportedCount() {
return *reinterpret_cast<int*>((uintptr_t)(this) + 0x100);
}
auto GetSimpleWeaponName() {
return *reinterpret_cast<const char**>((uintptr_t)(this) + 0x210);
}
auto GetSimpleWeaponName() {
return *reinterpret_cast<const char**>((uintptr_t)(this) + 0x210);
}
auto GetLoadoutSlot() {
return *reinterpret_cast<int*>((uintptr_t)(this) + 0x2E8);
}
auto GetLoadoutSlot() {
return *reinterpret_cast<int*>((uintptr_t)(this) + 0x2E8);
}
char pad0[0x8]; // vtable
void* m_pKVItem;
uint16_t m_nDefIndex;
CUtlVector_NativeSdk<uint16_t> m_nAssociatedItemsDefIndexes;
bool m_bEnabled;
const char* m_szPrefab;
uint8_t m_unMinItemLevel;
uint8_t m_unMaxItemLevel;
uint8_t m_nItemRarity;
uint8_t m_nItemQuality;
uint8_t m_nForcedItemQuality;
uint8_t m_nDefaultDropItemQuality;
uint8_t m_nDefaultDropQuantity;
CUtlVector_NativeSdk<void*> m_vecStaticAttributes;
uint8_t m_nPopularitySeed;
void* m_pPortraitsKV;
const char* m_pszItemBaseName;
bool m_bProperName;
const char* m_pszItemTypeName;
uint32_t m_unItemTypeID;
const char* m_pszItemDesc;
char pad0[0x8]; // vtable
void* m_pKVItem;
uint16_t m_nDefIndex;
CUtlVector_NativeSdk<uint16_t> m_nAssociatedItemsDefIndexes;
bool m_bEnabled;
const char* m_szPrefab;
uint8_t m_unMinItemLevel;
uint8_t m_unMaxItemLevel;
uint8_t m_nItemRarity;
uint8_t m_nItemQuality;
uint8_t m_nForcedItemQuality;
uint8_t m_nDefaultDropItemQuality;
uint8_t m_nDefaultDropQuantity;
CUtlVector_NativeSdk<void*> m_vecStaticAttributes;
uint8_t m_nPopularitySeed;
void* m_pPortraitsKV;
const char* m_pszItemBaseName;
bool m_bProperName;
const char* m_pszItemTypeName;
uint32_t m_unItemTypeID;
const char* m_pszItemDesc;
};
class CEconItemView {
public:
DECLARE_CLASS(CEconItemView);
auto GetCustomPaintKitIndex() { return CALL_VIRTUAL(int, 2, this); }
auto GetStaticData() {
return CALL_VIRTUAL(CEconItemDefinition*, 13, this);
}
public:
DECLARE_CLASS(CEconItemView);
auto GetCustomPaintKitIndex() { return CALL_VIRTUAL(int, 2, this); }
auto GetStaticData() {
return CALL_VIRTUAL(CEconItemDefinition*, 13, this);
}
};
class CAttributeContainer
{
public:
DECLARE_CLASS(CAttributeContainer);
class CAttributeContainer {
public:
DECLARE_CLASS(CAttributeContainer);
PSCHEMA_FIELD(CEconItemView, m_Item);
PSCHEMA_FIELD(CEconItemView, m_Item);
};
class CEconEntity {
public:
DECLARE_CLASS(CEconEntity);
public:
DECLARE_CLASS(CEconEntity);
PSCHEMA_FIELD(CAttributeContainer, m_AttributeManager);
PSCHEMA_FIELD(CAttributeContainer, m_AttributeManager);
};
class CBasePlayerWeapon : public CEconEntity
{
public:
DECLARE_CLASS(CBasePlayerWeapon);
class CBasePlayerWeapon : public CEconEntity {
public:
DECLARE_CLASS(CBasePlayerWeapon);
SCHEMA_FIELD(int, m_iClip1);
SCHEMA_FIELD(int, m_iClip2);
SCHEMA_FIELD(int, m_pReserveAmmo);
SCHEMA_FIELD(int, m_iClip1);
SCHEMA_FIELD(int, m_iClip2);
SCHEMA_FIELD(int, m_pReserveAmmo);
};
class CPlayer_WeaponServices {
public:
DECLARE_CLASS(CPlayer_WeaponServices)
SCHEMA_FIELD(CHandle, m_hActiveWeapon);
SCHEMA_FIELD(uint16_t, m_iAmmo);
public:
DECLARE_CLASS(CPlayer_WeaponServices)
SCHEMA_FIELD(CHandle, m_hActiveWeapon);
SCHEMA_FIELD(uint16_t, m_iAmmo);
};
class CBasePlayer {
public:
auto ForceRespawn() -> void;
public:
auto ForceRespawn() -> void;
};
class CPlayer_MovementServices {
public:
DECLARE_CLASS(CPlayer_MovementServices);
public:
DECLARE_CLASS(CPlayer_MovementServices);
};
class CCSPlayerController_InGameMoneyServices {
public:
DECLARE_CLASS(CCSPlayerController_InGameMoneyServices);
public:
DECLARE_CLASS(CCSPlayerController_InGameMoneyServices);
SCHEMA_FIELD(int, m_iAccount)
SCHEMA_FIELD(int, m_iAccount)
};
class CBasePlayerPawn : public CBaseEntity {
public:
DECLARE_CLASS(CBasePlayerPawn);
public:
DECLARE_CLASS(CBasePlayerPawn);
SCHEMA_FIELD(CPlayer_MovementServices*, m_pMovementServices)
SCHEMA_FIELD(CPlayer_WeaponServices*, m_pWeaponServices)
SCHEMA_FIELD(uint8_t**, m_pItemServices)
SCHEMA_FIELD(CPlayer_MovementServices*, m_pMovementServices)
SCHEMA_FIELD(CPlayer_WeaponServices*, m_pWeaponServices)
SCHEMA_FIELD(uint8_t**, m_pItemServices)
// m_hController
SCHEMA_FIELD(CBasePlayerController*, m_hController)
};
// Size: 0x1568
class CCSPlayerPawnBase : public CBasePlayerPawn
{
public:
DECLARE_CLASS(CCSPlayerPawnBase);
SCHEMA_FIELD(bool, m_bRespawning)
SCHEMA_FIELD(int, m_ArmorValue)
class CCSPlayerPawnBase : public CBasePlayerPawn {
public:
DECLARE_CLASS(CCSPlayerPawnBase);
SCHEMA_FIELD(bool, m_bRespawning)
SCHEMA_FIELD(int, m_ArmorValue)
};
class CCSPlayerPawn : public CCSPlayerPawnBase {
public:
DECLARE_CLASS(CCSPlayerPawn);
SCHEMA_FIELD(const char*, m_szLastPlaceName)
auto GetPlayerController() -> CCSPlayerController*;
public:
DECLARE_CLASS(CCSPlayerPawn);
SCHEMA_FIELD(const char*, m_szLastPlaceName)
auto GetPlayerController() -> CCSPlayerController*;
};
class CGameEntitySystem;
class CGameResourceService
{
public:
CGameEntitySystem* GetGameEntitySystem()
{
return *reinterpret_cast<CGameEntitySystem**>((uintptr_t)(this) + 0x58);
}
class CGameResourceService {
public:
CGameEntitySystem* GetGameEntitySystem() {
return *reinterpret_cast<CGameEntitySystem**>((uintptr_t)(this) + 0x58);
}
};
class CLocalize {
public:
auto FindSafe(const char* tokenName) -> const char*;
public:
auto FindSafe(const char* tokenName) -> const char*;
};
class Z_CBaseEntity : public CBaseEntity
{
public:
DECLARE_CLASS(CBaseEntity)
class Z_CBaseEntity : public CBaseEntity {
public:
DECLARE_CLASS(CBaseEntity)
SCHEMA_FIELD(CBitVec<64>, m_isSteadyState)
SCHEMA_FIELD(float, m_lastNetworkChange)
PSCHEMA_FIELD(void*, m_NetworkTransmitComponent)
SCHEMA_FIELD(int, m_iHealth)
SCHEMA_FIELD(int, m_iTeamNum)
SCHEMA_FIELD(Vector, m_vecBaseVelocity)
SCHEMA_FIELD(CCollisionProperty*, m_pCollision)
SCHEMA_FIELD(CBitVec<64>, m_isSteadyState)
SCHEMA_FIELD(float, m_lastNetworkChange)
PSCHEMA_FIELD(void*, m_NetworkTransmitComponent)
SCHEMA_FIELD(int, m_iHealth)
SCHEMA_FIELD(int, m_iTeamNum)
SCHEMA_FIELD(Vector, m_vecBaseVelocity)
SCHEMA_FIELD(CCollisionProperty*, m_pCollision)
};
class CCSGameRules {
public:
DECLARE_CLASS(CCSGameRules)
SCHEMA_FIELD(bool, m_bForceTeamChangeSilent)
};

View File

@@ -4,12 +4,15 @@ namespace Offset {
uint64_t GameResourceServicePtr;
uint64_t FireEventServerSidePtr;
uint64_t CGameEventManagerPtr;
uint64_t CCSGameRulesInterFacePtr;
uint64_t Host_SayPtr;
uint64_t Module_tier0;
uint64_t MaxPlayerNumsPtr;
HashFunction_t FnServerHashFunction;
StateChanged_t FnStateChanged;
NetworkStateChanged_t FnNetworkStateChanged;
//CreateGameRuleInterFace_t FnCreateCCSGameRulesInterFace;
namespace InterFaces {
CSchemaSystem* SchemaSystem;
IGameEventManager2* GameEventManager;
@@ -20,7 +23,9 @@ IVEngineServer2* IVEngineServer;
ISource2Server* ISource2ServerInterFace;
CLocalize* ILocalize;
INetworkServerService* INetworkServerServiceInteFace;
CCSGameRules* CCSGameRulesInterFace;
}; // namespace InterFaces
auto Init() -> bool {
CModule server("server.dll");
CModule schemasystem("schemasystem.dll");
@@ -28,43 +33,55 @@ auto Init() -> bool {
CModule localize("localize.dll");
// engine.dll
engine.FindPattern(pattern_MaxPlayerNumsPtr).ToAbsolute(3, 0).Get(MaxPlayerNumsPtr);
engine.FindPattern(pattern_MaxPlayerNumsPtr)
.ToAbsolute(3, 0)
.Get(MaxPlayerNumsPtr);
// server.dll
server.FindPattern(pattern_FireEventServerSide).Get(FireEventServerSidePtr);
server.FindPattern(pattern_NetworkStateChanged).Get(FnNetworkStateChanged);
server.FindPattern(pattern_FnStateChangedPtr).Get(FnStateChanged);
// 48 8D 05 4A 30 82 00 lea rax, ??_7CGameEventManager@@6B@
server.FindPattern(pattern_CGameEventManager)
.ToAbsolute(3, 0)
.Get(CGameEventManagerPtr);
server.FindPattern(pattern_CreateCCSGameRulesInterFacePtr)
.ToAbsolute(10, 0)
.Get(CCSGameRulesInterFacePtr);
server.FindPattern(pattern_fnHost_SayPtr).Get(Host_SayPtr);
server.FindPattern(pattern_ServerHashFunctionPtr).Get(FnServerHashFunction);
InterFaces::SchemaSystem = reinterpret_cast<CSchemaSystem*>(
schemasystem.FindInterface("SchemaSystem_001").Get());
//InterFaces::GameEventManager = reinterpret_cast<IGameEventManager2*>(
// engine.FindInterface("GameEventSystemServerV001").Get());
InterFaces::ILocalize = reinterpret_cast<CLocalize*>(localize.FindInterface("Localize_001").Get());
// InterFaces::GameEventManager = reinterpret_cast<IGameEventManager2*>(
// engine.FindInterface("GameEventSystemServerV001").Get());
InterFaces::ILocalize = reinterpret_cast<CLocalize*>(
localize.FindInterface("Localize_001").Get());
InterFaces::GameResourceServiceServer =
reinterpret_cast<CGameResourceService*>(
engine.FindInterface("GameResourceServiceServerV001").Get());
InterFaces::IVEngineServer = reinterpret_cast<IVEngineServer2*>(
engine.FindInterface("Source2EngineToServer001").Get());
InterFaces::INetworkServerServiceInteFace = reinterpret_cast<INetworkServerService*>(
engine.FindInterface("NetworkServerService_001").Get());
InterFaces::INetworkServerServiceInteFace =
reinterpret_cast<INetworkServerService*>(
engine.FindInterface("NetworkServerService_001").Get());
InterFaces::IServerGameClient = reinterpret_cast<IServerGameClients*>(
server.FindInterface("Source2GameClients001").Get());
InterFaces::ISource2ServerInterFace = reinterpret_cast<ISource2Server*>(
server.FindInterface("Source2Server001").Get());
if (InterFaces::ISource2ServerInterFace) {
InterFaces::GameEventManager = (IGameEventManager2*)(CALL_VIRTUAL(uintptr_t, 91, InterFaces::ISource2ServerInterFace) - 8);
InterFaces::GameEventManager =
(IGameEventManager2*)(CALL_VIRTUAL(
uintptr_t, 91,
InterFaces::ISource2ServerInterFace) -
8);
}
InterFaces::CGameEventManger =
reinterpret_cast<CGameEventManager*>(CGameEventManagerPtr);
//global::MaxPlayers = *(int*)((char*)MaxPlayerNumsPtr + 2);
// client.FindPattern(pattern_FireEventServerSide).Get(FireEventServerSidePtr);
InterFaces::CCSGameRulesInterFace =
reinterpret_cast<CCSGameRules*>(CCSGameRulesInterFacePtr + (8 * 2));
// global::MaxPlayers = *(int*)((char*)MaxPlayerNumsPtr + 2);
// client.FindPattern(pattern_FireEventServerSide).Get(FireEventServerSidePtr);
global::MaxPlayers = 64;
LOG("[huoji]FireEventServerSidePtr : %llx \n", FireEventServerSidePtr);
@@ -87,14 +104,17 @@ auto Init() -> bool {
InterFaces::IVEngineServer);
LOG("[huoji]InterFaces::ISource2ServerInterFace : %llx \n",
InterFaces::ISource2ServerInterFace);
LOG("[huoji]InterFaces::CCSGameRulesInterFace : %llx \n", InterFaces::CCSGameRulesInterFace);
//LOG("m_bForceTeamChangeSilent: %d \n", InterFaces::CCSGameRulesInterFace->m_bForceTeamChangeSilent());
// GetOffsets();
LOG("init offset success !\n");
//LOG("FnServerHashFunction: %llx \n", FnServerHashFunction("here", sizeof("here") - 1, 0x31415926));
// LOG("FnServerHashFunction: %llx \n", FnServerHashFunction("here",
// sizeof("here") - 1, 0x31415926));
return FnServerHashFunction && Host_SayPtr && InterFaces::IVEngineServer &&
InterFaces::GameResourceServiceServer &&
InterFaces::IServerGameClient && InterFaces::GameEventManager &&
InterFaces::SchemaSystem && FireEventServerSidePtr &&
FnNetworkStateChanged;
InterFaces::SchemaSystem && FireEventServerSidePtr && FnNetworkStateChanged;
}
} // namespace Offset

View File

@@ -2,27 +2,38 @@
#include "head.h"
#define SERVER_HASH_FUCNTION_KEY 0x31415926
class CEntityInstance;
typedef uint64_t(__fastcall* HashFunction_t)(const char*, unsigned int, unsigned int);
typedef void(__fastcall* StateChanged_t)(void* networkTransmitComponent, CEntityInstance* ent, uint64_t offset, int a4, int a5);
typedef void(__fastcall* NetworkStateChanged_t)(uintptr_t chainEntity, uintptr_t offset, uintptr_t a3);
typedef uint64_t(__fastcall* HashFunction_t)(const char*, unsigned int,
unsigned int);
typedef void(__fastcall* StateChanged_t)(void* networkTransmitComponent,
CEntityInstance* ent, uint64_t offset,
int a4, int a5);
typedef void(__fastcall* NetworkStateChanged_t)(uintptr_t chainEntity,
uintptr_t offset, uintptr_t a3);
typedef void*(__fastcall* CreateGameRuleInterFace_t)();
class CSchemaSystem;
class CGameResourceService;
class CLocalize;
class CCSGameRules;
namespace Offset {
namespace InterFaces {
extern CSchemaSystem* SchemaSystem;
extern IGameEventManager2* GameEventManager;
extern CGameEventManager* CGameEventManger;
extern CGameResourceService* GameResourceServiceServer;
extern IServerGameClients* IServerGameClient;
extern IVEngineServer2* IVEngineServer;
extern CLocalize* ILocalize;
extern INetworkServerService* INetworkServerServiceInteFace;
};
static const auto pattern_CGameEventManager = THE_GAME_SIG("48 ?? ?? ?? ?? ?? ?? 48 89 ?? ?? ?? 48 89 01 48 8B D9 48 ?? ?? ?? ?? ?? ?? 48 89 ?? ?? E8 ?? ?? ?? ?? 48 ?? ?? ?? ?? ?? ??");
static const auto pattern_NetworkStateChanged = THE_GAME_SIG("4C 8B C9 48 8B 09 48 85 C9 74 ? 48 8B 41 10");
static const auto pattern_FnStateChangedPtr = THE_GAME_SIG("48 89 54 24 10 55 53 57 41 55");
extern CSchemaSystem* SchemaSystem;
extern IGameEventManager2* GameEventManager;
extern CGameEventManager* CGameEventManger;
extern CGameResourceService* GameResourceServiceServer;
extern IServerGameClients* IServerGameClient;
extern IVEngineServer2* IVEngineServer;
extern CLocalize* ILocalize;
extern INetworkServerService* INetworkServerServiceInteFace;
extern ISource2Server* ISource2ServerInterFace;
extern CCSGameRules* CCSGameRulesInterFace;
}; // namespace InterFaces
static const auto pattern_CGameEventManager = THE_GAME_SIG(
"48 ?? ?? ?? ?? ?? ?? 48 89 ?? ?? ?? 48 89 01 48 8B D9 48 ?? ?? ?? ?? ?? "
"?? 48 89 ?? ?? E8 ?? ?? ?? ?? 48 ?? ?? ?? ?? ?? ??");
static const auto pattern_NetworkStateChanged =
THE_GAME_SIG("4C 8B C9 48 8B 09 48 85 C9 74 ? 48 8B 41 10");
static const auto pattern_FnStateChangedPtr =
THE_GAME_SIG("48 89 54 24 10 55 53 57 41 55");
static const auto pattern_FireEventServerSide = THE_GAME_SIG(
"40 53 57 41 54 41 55 41 56 48 ?? ?? ?? 4C 8B F2 4C 8B E1 BA ?? ?? ?? "
"?? 48 ?? ?? ?? ?? ?? ?? 45 0F B6 E8 E8 ?? ?? ?? ?? 48 85 C0 75 ?? 48 "
@@ -37,10 +48,16 @@ static const auto pattern_fnGetLocalPlayerController =
//"\"Console<0>\" say \"%s\"\n"
static const auto pattern_fnHost_SayPtr =
THE_GAME_SIG("44 89 4C 24 ?? 44 88 44 24 ?? 55 53 56 57 41 54 41 55");
static const auto pattern_ServerHashFunctionPtr =
THE_GAME_SIG("48 89 ?? ?? ?? 57 48 ?? ?? ?? ?? ?? ?? 33 C0 8B DA 41 8B F8 48 89 ?? ?? ?? 4C 8B C1 C7 44 ?? ?? ?? ?? ?? ?? 44 8B CA 89 44 ?? ?? 48 8D ?? ?? ?? 88 44 ?? ?? 33 D2");
static const auto pattern_MaxPlayerNumsPtr =
static const auto pattern_ServerHashFunctionPtr = THE_GAME_SIG(
"48 89 ?? ?? ?? 57 48 ?? ?? ?? ?? ?? ?? 33 C0 8B DA 41 8B F8 48 89 ?? ?? "
"?? 4C 8B C1 C7 44 ?? ?? ?? ?? ?? ?? 44 8B CA 89 44 ?? ?? 48 8D ?? ?? ?? "
"88 44 ?? ?? 33 D2");
static const auto pattern_MaxPlayerNumsPtr =
THE_GAME_SIG("41 3B 87 ?? ?? ?? ?? 0F 8E ?? ?? ?? ?? 8B 0D ?? ?? ?? ??");
static const auto pattern_CreateCCSGameRulesInterFacePtr = THE_GAME_SIG(
"40 53 48 ?? ?? ?? B9 ?? ?? ?? ?? E8 ?? ?? ?? ?? 33 D2 41 ?? ?? ?? ?? ?? "
"48 8B C8 48 8B D8 E8 ?? ?? ?? ?? 48 85 DB");
extern uint64_t GameResourceServicePtr;
extern uint64_t FireEventServerSidePtr;
extern uint64_t Module_tier0;
@@ -50,6 +67,5 @@ extern HashFunction_t FnServerHashFunction;
extern StateChanged_t FnStateChanged;
extern NetworkStateChanged_t FnNetworkStateChanged;
auto Init() -> bool;
}; // namespace Offset

View File

@@ -12,6 +12,16 @@ struct _luaApi_WeaponInfo {
int weaponType;
};
namespace ScriptApis {
auto TimerCallBack(_GameTimer* timer) -> void {
LOG("excute timer: %d %d m_bRepeat: %d\n", timer->m_iLuaCallBackFn, timer->m_iParamIndex, timer->m_bRepeat);
lua_rawgeti(timer->m_luaVm, LUA_REGISTRYINDEX, timer->m_iLuaCallBackFn);
lua_rawgeti(timer->m_luaVm, LUA_REGISTRYINDEX, timer->m_iParamIndex);
lua_pcall(timer->m_luaVm, 1, 0, 0);
if (timer->m_bRepeat == false) {
luaL_unref(timer->m_luaVm, LUA_REGISTRYINDEX, timer->m_iLuaCallBackFn);
luaL_unref(timer->m_luaVm, LUA_REGISTRYINDEX, timer->m_iParamIndex);
}
}
// <20><><EFBFBD><EFBFBD><EFBFBD>Ƿ<EFBFBD><C7B7><EFBFBD>ֵ<EFBFBD><D6B5><EFBFBD><EFBFBD>,<2C><><EFBFBD><EFBFBD>ֵ<EFBFBD><D6B5><EFBFBD><EFBFBD>Ҫ<EFBFBD>Լ<EFBFBD>push<73><68>stack<63><6B>
auto luaApi_ListenToGameEvent(lua_State* luaVm) -> int {
const auto eventName = lua_tostring(luaVm, 1);
@@ -99,6 +109,7 @@ auto luaApi_RespawnPlayer(lua_State* luaVm) -> int {
}
auto playerController = reinterpret_cast<CCSPlayerController*>(player);
auto playerPawn = playerController->m_hPawn().Get<CCSPlayerPawn>();
playerPawn->m_bRespawning(false);
} while (false);
lua_pop(luaVm, 1);
@@ -256,9 +267,128 @@ auto luaApi_GetPlayerCurrentWeaponInfo(lua_State* luaVm) -> _luaApi_WeaponInfo {
: (itemStaticData->IsWeapon() ? _luaApi_WeaponType::kGun
: _luaApi_WeaponType::kOther));
} while (false);
return info;
}
auto luaApi_CreateTimer(lua_State* luaVm) -> int {
// param: time:float, callback:function, params:lua_table
const auto time = lua_tonumber(luaVm, 1);
const auto repeat = lua_toboolean(luaVm, 2);
const auto preserveMapChange = lua_toboolean(luaVm, 3);
auto timerHandle = 0;
do {
const auto params = lua_gettable(luaVm, 4);
const auto callback = luaL_ref(luaVm, LUA_REGISTRYINDEX);
LOG("luaApi_CreateTimer: params: %d callback: %d \n", params, callback);
timerHandle = GameTimer::AddTimer(new _GameTimer{
.m_flTime = (float)time,
.m_bRepeat = (bool)repeat,
.m_bPreserveMapChange = (bool)preserveMapChange,
.m_luaVm = luaVm,
.m_iParamIndex = params,
.m_iLuaCallBackFn = callback
});
} while (false);
lua_pop(luaVm, 5);
lua_pushinteger(luaVm, timerHandle);
return 1;
}
auto luaApi_CheckPlayerIsAlive(lua_State* luaVm) -> int {
// param: playerIndex:int
const auto playerIndex = lua_tointeger(luaVm, 1);
auto isAlive = false;
CGameEntitySystem* EntitySystem = CGameEntitySystem::GetInstance();
do {
if (EntitySystem == nullptr || playerIndex == 0) {
break;
}
auto player = EntitySystem->GetBaseEntity(playerIndex);
if (player == nullptr) {
break;
}
if (player->IsBasePlayerController() == false) {
break;
}
auto playerController = reinterpret_cast<CCSPlayerController*>(player);
isAlive = playerController->m_bPawnIsAlive();
} while (false);
lua_pop(luaVm, 1);
lua_pushboolean(luaVm, isAlive);
return 1;
}
auto luaApi_GetPlayerTeam(lua_State* luaVm) -> int {
// param: playerIndex:int
const auto playerIndex = lua_tointeger(luaVm, 1);
auto team = 0;
CGameEntitySystem* EntitySystem = CGameEntitySystem::GetInstance();
do {
if (EntitySystem == nullptr || playerIndex == 0) {
break;
}
auto player = EntitySystem->GetBaseEntity(playerIndex);
if (player == nullptr) {
break;
}
if (player->IsBasePlayerController() == false) {
break;
}
auto playerController = reinterpret_cast<CCSPlayerController*>(player);
team = playerController->m_iTeamNum();
} while (false);
lua_pop(luaVm, 1);
lua_pushinteger(luaVm, team);
return 1;
}
auto luaApi_SetPlayerTeam(lua_State* luaVm) -> int {
// param: playerIndex:int, team:int
const auto playerIndex = lua_tointeger(luaVm, 1);
const auto team = lua_tointeger(luaVm, 2);
auto isSuccess = false;
CGameEntitySystem* EntitySystem = CGameEntitySystem::GetInstance();
do {
if (EntitySystem == nullptr || playerIndex == 0) {
break;
}
auto player = EntitySystem->GetBaseEntity(playerIndex);
if (player == nullptr) {
break;
}
if (player->IsBasePlayerController() == false) {
break;
}
auto playerController = reinterpret_cast<CCSPlayerController*>(player);
playerController->m_iTeamNum() = team;
isSuccess = true;
} while (false);
lua_pop(luaVm, 2);
lua_pushboolean(luaVm, isSuccess);
return 1;
}
auto luaApi_CheckPlayerIsInServer(lua_State* luaVm) -> int {
// param: playerIndex:int
const auto playerIndex = lua_tointeger(luaVm, 1);
auto isInServer = false;
CGameEntitySystem* EntitySystem = CGameEntitySystem::GetInstance();
do {
if (EntitySystem == nullptr || playerIndex == 0) {
break;
}
auto player = EntitySystem->GetBaseEntity(playerIndex);
if (player == nullptr) {
break;
}
if (player->IsBasePlayerController() == false) {
break;
}
isInServer = true;
} while (false);
lua_pop(luaVm, 1);
lua_pushboolean(luaVm, isInServer);
return 1;
}
auto initFunciton(lua_State* luaVm) -> void {
lua_register(luaVm, "ListenToGameEvent", luaApi_ListenToGameEvent);
lua_register(luaVm, "luaApi_SetPlayerCurrentWeaponAmmo",
@@ -270,7 +400,12 @@ auto initFunciton(lua_State* luaVm) -> void {
lua_register(luaVm, "luaApi_SetPlayerArmorValue",
luaApi_SetPlayerArmorValue);
lua_register(luaVm, "luaApi_RespawnPlayer", luaApi_RespawnPlayer);
lua_register(luaVm, "luaApi_CreateTimer", luaApi_CreateTimer);
lua_register(luaVm, "luaApi_CheckPlayerIsAlive", luaApi_CheckPlayerIsAlive);
lua_register(luaVm, "luaApi_GetPlayerTeam", luaApi_GetPlayerTeam);
lua_register(luaVm, "luaApi_SetPlayerTeam", luaApi_SetPlayerTeam);
lua_register(luaVm, "luaApi_CheckPlayerIsInServer",
luaApi_CheckPlayerIsInServer);
// <20>Ҳ<EFBFBD>ϲ<EFBFBD><CFB2><EFBFBD><EFBFBD>
luabridge::getGlobalNamespace(luaVm)
.beginClass<_luaApi_WeaponInfo>("WeaponInfo")

View File

@@ -8,7 +8,9 @@ std::unordered_map<uint32_t, _CallbackNames> callbackNameWithEnumMap{
{hash_32_fnv1a_const("player_connect"), _CallbackNames::kOnPlayerConnect},
{hash_32_fnv1a_const("player_disconnect"),
_CallbackNames::kOnPlayerDisconnect},
{hash_32_fnv1a_const("player_death"), _CallbackNames::kOnPlayerDeath}};
{hash_32_fnv1a_const("player_death"), _CallbackNames::kOnPlayerDeath},
{hash_32_fnv1a_const("player_chat"), _CallbackNames::kOnPlayerSpeak},
};
auto CallBackNameToEnum(const char* name) -> _CallbackNames {
if (name == nullptr) {
return _CallbackNames::kError;
@@ -104,4 +106,27 @@ auto luaCall_onPlayerDeath(int victim, int killer, bool isHeadShot) -> void {
}
});
}
auto luaCall_onPlayerSpeak(int speaker, int chatType, std::string message)
-> bool {
bool result = false;
ExcuteCallbackInAllLuaVm(_CallbackNames::kOnPlayerSpeak,
[&](lua_State* luaVm, int refIndex) -> void {
lua_rawgeti(luaVm, LUA_REGISTRYINDEX,
refIndex);
if (lua_isfunction(luaVm, -1)) {
lua_pushinteger(luaVm, speaker);
lua_pushinteger(luaVm, chatType);
lua_pushstring(luaVm, message.c_str());
if (lua_pcall(luaVm, 3, 1, 0) != LUA_OK) {
LOG("Error calling Lua callback: %s\n",
lua_tostring(luaVm, -1));
lua_pop(luaVm, 1);
}
if (lua_isboolean(luaVm, -1)) {
result = lua_toboolean(luaVm, -1);
}
}
});
return result;
}
} // namespace ScriptCallBacks

View File

@@ -6,7 +6,8 @@ enum class _CallbackNames {
kError,
kOnPlayerConnect,
kOnPlayerDisconnect,
kOnPlayerDeath
kOnPlayerDeath,
kOnPlayerSpeak
};
extern std::unordered_map<lua_State*, std::unordered_map<_CallbackNames, int>>
callbackList;
@@ -19,4 +20,6 @@ auto luaCall_onPlayerDisconnect(int player, int slot, const char* pszName,
const char* pszAddress, bool bFakePlayer)
-> void;
auto luaCall_onPlayerDeath(int victim, int killer, bool isHeadShot) -> void;
auto luaCall_onPlayerSpeak(int speaker, int chatType, std::string message)
-> bool;
} // namespace ScriptCallBacks

View File

@@ -193,6 +193,7 @@ public:
class ISource2Server : public IAppSystem
{
public:
//vmt index 11
virtual bool Unknown0() const = 0;
virtual void SetGlobals(CGlobalVars* pGlobals) = 0;
@@ -213,6 +214,7 @@ public:
// The server should run physics/think on all edicts
// One of these bools is 'simulating'... probably
// index 19
virtual void GameFrame(bool simulating, bool bFirstTick, bool bLastTick) = 0;
// Returns true if the game DLL wants the server not to be made public.

View File

@@ -91,6 +91,7 @@ public:
class IEngineService : public IAppSystem
{
public:
//vmt index 11
virtual void* GetServiceDependencies(void) = 0;
virtual const char* GetName(void) const = 0;
virtual bool ShouldActivate(const char*) = 0;
@@ -107,10 +108,12 @@ public:
class INetworkServerService : public IEngineService
{
public:
//vmt index 22
virtual ~INetworkServerService() {}
virtual INetworkGameServer * GetIGameServer(void) = 0;
virtual bool IsActiveInGame(void) const = 0;
virtual bool IsMultiplayer(void) const = 0;
//vmt index 26
virtual void StartupServer(const GameSessionConfiguration_t& config, ISource2WorldSession* pWorldSession, const char*) = 0;
virtual void SetGameSpawnGroupMgr(IGameSpawnGroupMgr* pMgr) = 0;
virtual void AddServerPrerequisites(const GameSessionConfiguration_t&, const char*, void*, bool) = 0;

43
csgo2/timer.cpp Normal file
View File

@@ -0,0 +1,43 @@
#include "timer.h"
namespace ScriptApis {
extern auto TimerCallBack(_GameTimer* timer) -> void;
};
namespace GameTimer {
std::shared_mutex mutex_timerList;
std::vector<_GameTimer*> timerList;
auto AddTimer(_GameTimer* timer) -> int {
std::unique_lock<std::shared_mutex> lock(mutex_timerList);
timerList.push_back(timer);
return timerList.size() - 1;
};
auto CleanUpTimers() -> void {
std::unique_lock<std::shared_mutex> lock(mutex_timerList);
for (auto it = timerList.begin(); it != timerList.end();) {
if ((*it)->m_bPreserveMapChange) {
++it;
} else {
delete (*it);
it = timerList.erase(it);
}
}
};
auto ExcuteTimers() -> void {
std::shared_lock<std::shared_mutex> lock(mutex_timerList);
for (auto it = timerList.begin(); it != timerList.end();) {
if ((*it)->m_flLastExecute == -1) {
(*it)->m_flLastExecute = global::m_flUniversalTime;
}
if ((*it)->m_flLastExecute + (*it)->m_flTime <= global::m_flUniversalTime) {
ScriptApis::TimerCallBack(*it);
if ((*it)->m_bRepeat) {
(*it)->m_flLastExecute = global::m_flUniversalTime;
} else {
delete (*it);
it = timerList.erase(it);
continue;
}
}
++it;
}
}
}; // namespace GameTimer

18
csgo2/timer.h Normal file
View File

@@ -0,0 +1,18 @@
#pragma once
#include "head.h"
class _GameTimer {
public:
float m_flTime;
float m_flLastExecute = -1;
bool m_bRepeat;
bool m_bPreserveMapChange;
lua_State* m_luaVm;
int m_iParamIndex;
int m_iLuaCallBackFn;
};
namespace GameTimer {
auto AddTimer(_GameTimer* timer) -> int;
auto CleanUpTimers() -> void;
auto ExcuteTimers() -> void;
}; // namespace GameTimer

View File

@@ -9,13 +9,13 @@ void* VMTHook::Hook(int index, void* hk)
{
// Store the index and original function address
hooked_funcs.insert(std::make_pair(index, vmt[index]));
printf("vmt hook at: %p \n", vmt[index]);
// Change the memory's access rights, patch the address to our hook, restore original rights
DWORD old;
VirtualProtect(&vmt[index], sizeof(void*), PAGE_EXECUTE_READWRITE, &old);
vmt[index] = hk;
VirtualProtect(&vmt[index], sizeof(void*), old, NULL);
return hooked_funcs[index];
}