2022-04-09 16:16:40 +02:00
# pragma once
2022-11-27 21:53:54 +01:00
# include "public/ikeyvaluessystem.h"
2023-07-02 02:51:12 +02:00
# include "tier1/memstack.h"
# include "tier1/mempool.h"
# include "tier1/utlvector.h"
# include "tier1/utlmap.h"
2022-04-09 16:16:40 +02:00
2024-01-12 01:51:28 +01:00
class CKeyValuesSystem ;
/* ==== KEYVALUESSYSTEM ================================================================================================================================================= */
extern CKeyValuesSystem * g_pKeyValuesSystem ;
extern void * g_pKeyValuesMemPool ;
2024-01-12 00:32:17 +01:00
2022-11-27 21:53:54 +01:00
class CKeyValuesSystem : public IKeyValuesSystem // VTABLE @ 0x1413AA1E8 in R5pc_r5launch_N1094_CL456479_2019_10_30_05_20_PM
2022-04-09 16:16:40 +02:00
{
public :
2024-01-12 00:32:17 +01:00
CKeyValuesSystem ( ) ;
~ CKeyValuesSystem ( ) ;
// registers the size of the KeyValues in the specified instance
// so it can build a properly sized memory pool for the KeyValues objects
// the sizes will usually never differ but this is for versioning safety
virtual void RegisterSizeofKeyValues ( const ssize_t nSize ) ;
// allocates/frees a KeyValues object from the shared mempool
virtual void * AllocKeyValuesMemory ( const ssize_t nSize ) ;
virtual void FreeKeyValuesMemory ( void * const pMem ) ;
// symbol table access (used for key names)
virtual HKeySymbol GetSymbolForString ( const char * const szName , const bool bCreate = true ) ;
virtual const char * GetStringForSymbol ( const HKeySymbol symbol ) ;
// for debugging, adds KeyValues record into global list so we can track memory leaks
virtual void AddKeyValuesToMemoryLeakList ( const void * const pMem , const HKeySymbol name ) ;
virtual void RemoveKeyValuesFromMemoryLeakList ( const void * const pMem ) ;
// GetMemPool returns a global variable called m_pMemPool, it gets modified by AllocKeyValuesMemory and with FreeKeyValuesMemory you can see where to find it in FreeKeyValuesMemory.
virtual void * GetKeyValuesMemory ( void ) { return g_pKeyValuesMemPool ; }
2022-04-09 16:16:40 +02:00
2024-01-12 00:32:17 +01:00
// set/get a value for keyvalues resolution symbol
// e.g.: SetKeyValuesExpressionSymbol( "LOWVIOLENCE", true ) - enables [$LOWVIOLENCE]
virtual void SetKeyValuesExpressionSymbol ( const char * const szName , const bool bValue ) ;
virtual bool GetKeyValuesExpressionSymbol ( const char * const szName ) ;
// symbol table access from code with case-preserving requirements (used for key names)
virtual HKeySymbol GetSymbolForStringCaseSensitive ( HKeySymbol & hCaseInsensitiveSymbol , const char * const szName , const bool bCreate = true ) ;
2022-04-09 16:16:40 +02:00
private :
2024-01-12 00:32:17 +01:00
ssize_t m_iMaxKeyValuesSize ;
// string hash table
/*
Here ' s the way key values system data structures are laid out :
hash table with 2047 hash buckets :
[ 0 ] { hash_item_t }
[ 1 ]
[ 2 ]
. . .
each hash_item_t ' s stringIndex is an offset in m_Strings memory
at that offset we store the actual null - terminated string followed
by another 3 bytes for an alternative capitalization .
These 3 trailing bytes are set to 0 if no alternative capitalization
variants are present in the dictionary .
These trailing 3 bytes are interpreted as stringIndex into m_Strings
memory for the next alternative capitalization
Getting a string value by HKeySymbol : constant time access at the
string memory represented by stringIndex
Getting a symbol for a string value :
1 ) compute the hash
2 ) start walking the hash - bucket using special version of stricmp
until a case insensitive match is found
3 a ) for case - insensitive lookup return the found stringIndex
3 b ) for case - sensitive lookup keep walking the list of alternative
capitalizations using strcmp until exact case match is found
*/
2023-07-02 02:51:12 +02:00
CMemoryStack m_Strings ;
struct hash_item_t
{
2024-01-12 00:32:17 +01:00
int64_t stringIndex ;
2023-07-02 02:51:12 +02:00
hash_item_t * next ;
} ;
CUtlMemoryPool m_HashItemMemPool ;
CUtlVector < hash_item_t > m_HashTable ;
2024-01-12 00:32:17 +01:00
int CaseInsensitiveHash ( const char * const string , const int iBounds ) ;
2023-07-02 02:51:12 +02:00
struct MemoryLeakTracker_t
{
2024-01-12 00:32:17 +01:00
int64_t nameIndex ;
const void * pMem ;
2023-07-02 02:51:12 +02:00
} ;
2024-01-12 00:32:17 +01:00
static bool MemoryLeakTrackerLessFunc ( const MemoryLeakTracker_t & lhs , const MemoryLeakTracker_t & rhs )
{
return lhs . pMem < rhs . pMem ;
}
2023-07-02 02:51:12 +02:00
// Unknown less func.
void * m_pCompareFunc ;
CUtlRBTree < MemoryLeakTracker_t , int > m_KeyValuesTrackingList ;
CUtlMap < HKeySymbol , bool > m_KvConditionalSymbolTable ;
CThreadFastMutex m_Mutex ;
2022-04-09 16:16:40 +02:00
} ;
///////////////////////////////////////////////////////////////////////////////
class HKeyValuesSystem : public IDetour
{
2022-04-11 01:44:30 +02:00
virtual void GetAdr ( void ) const
2022-04-09 16:16:40 +02:00
{
2024-01-02 15:21:36 +01:00
LogVarAdr ( " g_pKeyValuesMemPool " , g_pKeyValuesMemPool ) ;
LogVarAdr ( " g_pKeyValuesSystem " , g_pKeyValuesSystem ) ;
2022-04-09 16:16:40 +02:00
}
2022-04-11 01:44:30 +02:00
virtual void GetFun ( void ) const { }
2022-04-18 03:35:08 +02:00
virtual void GetVar ( void ) const
{
2022-12-01 22:44:55 +01:00
g_pKeyValuesSystem = g_GameDll . FindPatternSIMD ( " 48 89 5C 24 ?? 48 89 6C 24 ?? 56 57 41 56 48 83 EC 40 48 8B F1 " )
2022-04-19 00:00:45 +02:00
. FindPatternSelf ( " 48 8D 0D ?? ?? ?? 01 " , CMemory : : Direction : : DOWN ) . ResolveRelativeAddressSelf ( 0x3 , 0x7 ) . RCast < CKeyValuesSystem * > ( ) ;
2022-04-18 03:35:08 +02:00
2022-12-01 22:44:55 +01:00
g_pKeyValuesMemPool = g_GameDll . FindPatternSIMD ( " 48 8B 05 ?? ?? ?? ?? C3 CC CC CC CC CC CC CC CC 48 85 D2 " ) . ResolveRelativeAddressSelf ( 0x3 , 0x7 ) . RCast < void * > ( ) ;
2022-04-18 03:35:08 +02:00
}
2022-04-11 01:44:30 +02:00
virtual void GetCon ( void ) const { }
2023-11-26 13:21:20 +01:00
virtual void Detour ( const bool bAttach ) const { }
2022-04-09 16:16:40 +02:00
} ;
///////////////////////////////////////////////////////////////////////////////