Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions configs/addons/counterstrikesharp/gamedata/gamedata.json
Original file line number Diff line number Diff line change
Expand Up @@ -265,5 +265,18 @@
"windows": 584,
"linux": 584
}
},
"NetworkStateChanged": {
"signatures": {
"library": "server",
"windows": "4C 8B C2 48 8B D1 48 8B 09",
"linux": "48 8B 07 48 85 C0 74 ? 48 8B 50 10"
}
},
"SetStateChanged": {
"offsets": {
"windows": 25,
"linux": 26
}
}
}
16 changes: 10 additions & 6 deletions src/core/cs2_sdk/schema.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -125,14 +125,18 @@ SchemaKey schema::GetOffset(const char* className, uint32_t classKey, const char
return tableMap->Element(memberIndex);
}

void SetStateChanged(uintptr_t entityInstance, int nOffset)
void NetworkStateChanged(uintptr_t chainEntity, uint32_t offset, uint32_t nArrayIndex, uint32_t nPathIndex)
{
reinterpret_cast<CEntityInstance*>(entityInstance)->NetworkStateChanged(nOffset);
CNetworkStateChangedInfo info(offset, nArrayIndex, nPathIndex);

if (counterstrikesharp::globals::NetworkStateChanged)
counterstrikesharp::globals::NetworkStateChanged(reinterpret_cast<void*>(chainEntity), info);
}

void ChainNetworkStateChanged(uintptr_t networkVarChainer, uint nLocalOffset)
void SetStateChanged(uintptr_t pEntity, uint32_t offset, uint32_t nArrayIndex, uint32_t nPathIndex)
{
CEntityInstance* pEntity = *reinterpret_cast<CEntityInstance**>(networkVarChainer);
if (pEntity && (pEntity->m_pEntity->m_flags & EF_IS_CONSTRUCTION_IN_PROGRESS) == 0)
pEntity->NetworkStateChanged(nLocalOffset, -1, *reinterpret_cast<ChangeAccessorFieldPathIndex_t*>(networkVarChainer + 32));
CNetworkStateChangedInfo info(offset, nArrayIndex, nPathIndex);

static auto fnOffset = counterstrikesharp::globals::gameConfig->GetOffset("SetStateChanged");
CALL_VIRTUAL(void, fnOffset, (void*)pEntity, &info);
}
115 changes: 72 additions & 43 deletions src/core/cs2_sdk/schema.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
#include <stdint.h>
#include "tier0/dbg.h"
#include "utils/virtual.h"
#include "tier1/utlvector.h"

#include <string>
#include <vector>
Expand All @@ -36,9 +37,37 @@ struct SchemaKey
bool networked;
};

class Z_CBaseEntity;
void SetStateChanged(uintptr_t pEntity, int offset);
void ChainNetworkStateChanged(uintptr_t pEntity, int offset);
class CBaseEntity;
struct CNetworkStateChangedInfo
{
CNetworkStateChangedInfo() = delete;

CNetworkStateChangedInfo(uint32_t nOffset, uint32_t nArrayIndex, uint32_t nPathIndex)
{
m_vecOffsetData.EnsureCount(1);
m_vecOffsetData[0] = nOffset;

unk_30 = -1;

unk_3c = 0;

m_nArrayIndex = nArrayIndex;
m_nPathIndex = nPathIndex;
}

private:
int m_nSize; // 0x0
CUtlVector<uint32_t> m_vecOffsetData; // 0x8
char* m_pszFieldName{}; // 0x20
char* m_pszFileName{}; // 0x28
uint32_t unk_30 = -1; // 0x30
uint32_t m_nArrayIndex{}; // 0x34
uint32_t m_nPathIndex{}; // 0x38
uint16_t unk_3c{}; // 0x3c
}; // Size: 0x3e

void NetworkStateChanged(uintptr_t chainEntity, uint32_t offset, uint32_t nArrayIndex = -1, uint32_t nPathIndex = -1);
void SetStateChanged(uintptr_t pEntity, uint32_t offset, uint32_t nArrayIndex = -1, uint32_t nPathIndex = -1);

constexpr uint32_t val_32_const = 0x811c9dc5;
constexpr uint32_t prime_32_const = 0x1000193;
Expand Down Expand Up @@ -99,39 +128,39 @@ int16_t FindChainOffset(const char* className);
SchemaKey GetOffset(const char* className, uint32_t classKey, const char* memberName, uint32_t memberKey);
} // namespace schema

#define SCHEMA_FIELD_OFFSET(type, varName, extra_offset) \
class varName##_prop \
{ \
public: \
std::add_lvalue_reference_t<type> Get() \
{ \
static constexpr auto datatable_hash = hash_32_fnv1a_const(ThisClassName); \
static constexpr auto prop_hash = hash_32_fnv1a_const(#varName); \
\
static const auto m_key = schema::GetOffset(ThisClassName, datatable_hash, #varName, prop_hash); \
\
static const size_t offset = offsetof(ThisClass, varName); \
ThisClass* pThisClass = (ThisClass*)((byte*)this - offset); \
\
return *reinterpret_cast<std::add_pointer_t<type>>((uintptr_t)(pThisClass) + m_key.offset + extra_offset); \
} \
void Set(type val) \
{ \
static constexpr auto datatable_hash = hash_32_fnv1a_const(ThisClassName); \
static constexpr auto prop_hash = hash_32_fnv1a_const(#varName); \
\
static const auto m_key = schema::GetOffset(ThisClassName, datatable_hash, #varName, prop_hash); \
\
static const auto m_chain = schema::FindChainOffset(ThisClassName); \
\
static const size_t offset = offsetof(ThisClass, varName); \
ThisClass* pThisClass = (ThisClass*)((byte*)this - offset); \
\
if (m_chain != 0 && m_key.networked) \
{ \
DevMsg("Found chain offset %d for %s::%s\n", m_chain, ThisClassName, #varName); \
ChainNetworkStateChanged((uintptr_t)(pThisClass) + m_chain, m_key.offset + extra_offset); \
} \
#define SCHEMA_FIELD_OFFSET(type, varName, extra_offset) \
class varName##_prop \
{ \
public: \
std::add_lvalue_reference_t<type> Get() \
{ \
static constexpr auto datatable_hash = hash_32_fnv1a_const(ThisClassName); \
static constexpr auto prop_hash = hash_32_fnv1a_const(#varName); \
\
static const auto m_key = schema::GetOffset(ThisClassName, datatable_hash, #varName, prop_hash); \
\
static const size_t offset = offsetof(ThisClass, varName); \
ThisClass* pThisClass = (ThisClass*)((byte*)this - offset); \
\
return *reinterpret_cast<std::add_pointer_t<type>>((uintptr_t)(pThisClass) + m_key.offset + extra_offset); \
} \
void Set(type val) \
{ \
static constexpr auto datatable_hash = hash_32_fnv1a_const(ThisClassName); \
static constexpr auto prop_hash = hash_32_fnv1a_const(#varName); \
\
static const auto m_key = schema::GetOffset(ThisClassName, datatable_hash, #varName, prop_hash); \
\
static const auto m_chain = schema::FindChainOffset(ThisClassName); \
\
static const size_t offset = offsetof(ThisClass, varName); \
ThisClass* pThisClass = (ThisClass*)((byte*)this - offset); \
\
if (m_chain != 0 && m_key.networked) \
{ \
DevMsg("Found chain offset %d for %s::%s\n", m_chain, ThisClassName, #varName); \
SetStateChanged((uintptr_t)(pThisClass) + m_chain, m_key.offset + extra_offset); \
} \
else if (m_key.networked) \
{ \
/* WIP: Works fine for most props, but inlined classes in the middle of a class will \
Expand All @@ -140,13 +169,13 @@ SchemaKey GetOffset(const char* className, uint32_t classKey, const char* member
else \
CALL_VIRTUAL(void, 1, pThisClass, m_key.offset + extra_offset, 0xFFFFFFFF, 0xFFFFFFFF); \
} \
*reinterpret_cast<std::add_pointer_t<type>>((uintptr_t)(pThisClass) + m_key.offset + extra_offset) = val; \
} \
operator std::add_lvalue_reference_t<type>() { return Get(); } \
std::add_lvalue_reference_t<type> operator()() { return Get(); } \
std::add_lvalue_reference_t<type> operator->() { return Get(); } \
void operator()(type val) { Set(val); } \
void operator=(type val) { Set(val); } \
*reinterpret_cast<std::add_pointer_t<type>>((uintptr_t)(pThisClass) + m_key.offset + extra_offset) = val; \
} \
operator std::add_lvalue_reference_t<type>() { return Get(); } \
std::add_lvalue_reference_t<type> operator()() { return Get(); } \
std::add_lvalue_reference_t<type> operator->() { return Get(); } \
void operator()(type val) { Set(val); } \
void operator=(type val) { Set(val); } \
} varName;

#define SCHEMA_FIELD_POINTER_OFFSET(type, varName, extra_offset) \
Expand Down
9 changes: 9 additions & 0 deletions src/core/globals.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,15 @@ void Initialize()
return;
}

NetworkStateChanged =
reinterpret_cast<NetworkStateChanged_t*>(modules::server->FindSignature(globals::gameConfig->GetSignature("NetworkStateChanged")));

if (NetworkStateChanged == nullptr)
{
CSSHARP_CORE_ERROR("Failed to find signature for \'NetworkStateChanged\'");
return;
}

auto m_hook = funchook_create();
funchook_prepare(m_hook, (void**)&GameEventManagerInit, (void*)&DetourGameEventManagerInit);
funchook_install(m_hook, 0);
Expand Down
3 changes: 3 additions & 0 deletions src/core/globals.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ class CounterStrikeSharpMMPlugin;
class CGameEntitySystem;
class IGameEventListener2;
class CSchemaSystem;
class CNetworkStateChangedInfo;

namespace counterstrikesharp {
class EntityListener;
Expand Down Expand Up @@ -120,11 +121,13 @@ extern const float engine_fixed_tick_interval;

typedef void GameEventManagerInit_t(IGameEventManager2* gameEventManager);
typedef IGameEventListener2* GetLegacyGameEventListener_t(CPlayerSlot slot);
typedef void* NetworkStateChanged_t(void* chainEntity, CNetworkStateChangedInfo& info);

static void DetourGameEventManagerInit(IGameEventManager2* gameEventManager);

extern bool gameLoopInitialized;
extern GetLegacyGameEventListener_t* GetLegacyGameEventListener;
inline NetworkStateChanged_t* NetworkStateChanged = nullptr;
extern std::thread::id gameThreadId;

void Initialize();
Expand Down