Skip to content

Commit dbbb73c

Browse files
Change CScriptNetPropManager cache to enable reading more values
1 parent 2d01391 commit dbbb73c

1 file changed

Lines changed: 96 additions & 51 deletions

File tree

sp/src/game/shared/mapbase/vscript_singletons.cpp

Lines changed: 96 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -128,27 +128,22 @@ class CScriptNetPropManager
128128
typedef SendTable NetTable;
129129
typedef ServerClass NetworkClass;
130130

131-
NetworkClass *GetNetworkClass( CBaseEntity* p ) { return p->GetServerClass(); }
132-
NetTable *GetNetTable( NetworkClass* p ) { return p->m_pTable; }
131+
static NetworkClass *GetNetworkClass( CBaseEntity *p ) { return p->GetServerClass(); }
132+
static NetTable *GetNetTable( NetworkClass *p ) { return p->m_pTable; }
133133

134-
void NetworkStateChanged( CBaseEntity* p, int o ) { p->NetworkProp()->NetworkStateChanged( o ); }
134+
static void NetworkStateChanged( CBaseEntity *p, int o ) { p->NetworkProp()->NetworkStateChanged( o ); }
135135
#else
136136
typedef RecvProp NetProp;
137137
typedef RecvTable NetTable;
138138
typedef ClientClass NetworkClass;
139139

140-
NetworkClass *GetNetworkClass( CBaseEntity* p ) { return p->GetClientClass(); }
141-
NetTable *GetNetTable( NetworkClass* p ) { return p->m_pRecvTable; }
140+
static NetworkClass *GetNetworkClass( CBaseEntity *p ) { return p->GetClientClass(); }
141+
static NetTable *GetNetTable( NetworkClass *p ) { return p->m_pRecvTable; }
142142

143-
void NetworkStateChanged( CBaseEntity*, int ) {}
143+
static void NetworkStateChanged( CBaseEntity*, int ) {}
144144
#endif
145145

146-
int GetClassID( CBaseEntity *p )
147-
{
148-
return GetNetworkClass( p )->m_ClassID;
149-
}
150-
151-
int GetIntPropSize( NetProp *pProp )
146+
static int GetIntPropSize( NetProp *pProp )
152147
{
153148
Assert( pProp->GetType() == DPT_Int );
154149

@@ -181,12 +176,12 @@ class CScriptNetPropManager
181176
#endif
182177
}
183178

184-
bool IsEHandle( NetProp *pProp )
179+
static bool IsEHandle( NetProp *pProp )
185180
{
186181
return ( pProp->GetProxyFn() == DataTableProxy_EHandle );
187182
}
188183

189-
bool IsUtlVector( NetProp *pProp )
184+
static bool IsUtlVector( NetProp *pProp )
190185
{
191186
#ifdef GAME_DLL
192187
SendVarProxyFn proxy = pProp->GetProxyFn();
@@ -257,10 +252,9 @@ class CScriptNetPropManager
257252
// element size in bytes
258253
unsigned int elemsize : VARINFO_ELEMSIZE_BITS;
259254

260-
// Following are only used in integer netprops to handle unsigned and size casting
255+
// Only used in integer netprops to handle unsigned and size casting
261256
unsigned int isUnsigned : 1;
262257
unsigned int isNotNetworked : 1;
263-
264258
unsigned int isGameRules : 1;
265259

266260
int GetOffset( int index )
@@ -269,35 +263,87 @@ class CScriptNetPropManager
269263
}
270264
};
271265

266+
struct varsource_t
267+
{
268+
void *source;
269+
varinfo_t info;
270+
};
271+
272+
struct vardictelem_t
273+
{
274+
CCopyableUtlVector< varsource_t > sources;
275+
};
276+
272277
// Wrapper to be able to set case sensitive comparator in node insertion
273-
class vardict_t : public CUtlDict< varinfo_t >
278+
class vardict_t : public CUtlDict< vardictelem_t >
274279
{
275280
public:
276-
vardict_t() : CUtlDict< varinfo_t >( k_eDictCompareTypeCaseSensitive ) {}
281+
vardict_t() : CUtlDict< vardictelem_t >( k_eDictCompareTypeCaseSensitive ) {}
277282
};
278283

279-
// NOTE: This is lazy and inefficient.
280-
// Simply map highest level class id to unique caches.
281-
CUtlVector< int > m_EntMap;
282-
CUtlVector< vardict_t > m_VarDicts;
284+
// Different entities can have unique network tables while sharing data maps,
285+
// or unique data maps while sharing network tables (e.g. server only entities).
286+
// The cache needs to be able to differentiate the source of the variable info
287+
// while being quick to access.
288+
//
289+
// While storing the origin table (e.g. DT_BaseEntity for DT_HL2_Player->m_vecOrigin)
290+
// keeps the cache size small, it would have runtime impact from
291+
// checking base tables and pointer chasing.
292+
// Instead, store the highest level table identifiers even if they are identical to
293+
// existing variables. (e.g.
294+
// storing DT_HL2_Player and DT_PhysicsProp for the variable DT_BaseEntity->m_vecOrigin)
295+
//
296+
// Fetching varinfo from cache now does one sorted string lookup (RB tree)
297+
// and 2 pointer comparisons for each class type that was fetched for that variable name
298+
// (practically a very low number because NetProps is used more often for unique variables than not).
299+
//
300+
// This is a quick, not well thought out solution
301+
vardict_t m_VarDicts;
283302

284-
varinfo_t *CacheNew( CBaseEntity *pEnt, const char *szProp, bool bNetworked )
303+
static varsource_t *CacheFind( CBaseEntity *pEnt, vardictelem_t *pElem )
285304
{
286-
int idx = m_EntMap.Find( GetClassID( pEnt ) );
287-
if ( idx == m_EntMap.InvalidIndex() )
305+
NetTable *pNetTable = GetNetTable( GetNetworkClass( pEnt ) );
306+
datamap_t *pDataMap = pEnt->GetDataDescMap();
307+
#ifdef CLIENT_DLL
308+
datamap_t *pPredMap = pEnt->GetPredDescMap();
309+
#endif
310+
311+
FOR_EACH_VEC( pElem->sources, i )
288312
{
289-
// Vector indices are kept in parallel as a workaround for encapsulating maps
290-
idx = m_EntMap.AddToTail( GetClassID( pEnt ) );
291-
m_VarDicts.AddToTail();
313+
varsource_t *pSrc = &pElem->sources.Element( i );
314+
315+
if ( pSrc->source == pNetTable )
316+
return pSrc;
317+
318+
if ( pSrc->source == pDataMap )
319+
return pSrc;
320+
#ifdef CLIENT_DLL
321+
if ( pSrc->source == pPredMap )
322+
return pSrc;
323+
#endif
292324
}
293325

294-
vardict_t &dict = m_VarDicts.Element( idx );
326+
return NULL;
327+
}
295328

296-
idx = dict.Find( szProp );
297-
if ( idx == dict.InvalidIndex() )
298-
idx = dict.Insert( szProp );
329+
varinfo_t *CacheNew( CBaseEntity *pEnt, const char *szProp, void *pSource, bool bNetworked )
330+
{
331+
int idx = m_VarDicts.Find( szProp );
332+
if ( idx == m_VarDicts.InvalidIndex() )
333+
idx = m_VarDicts.Insert( szProp );
334+
335+
vardictelem_t *pElem = &m_VarDicts.Element( idx );
336+
varsource_t *pSrc = CacheFind( pEnt, pElem );
299337

300-
varinfo_t *pInfo = &dict.Element( idx );
338+
if ( !pSrc )
339+
{
340+
idx = pElem->sources.AddToTail();
341+
pSrc = &pElem->sources.Element( idx );
342+
}
343+
344+
pSrc->source = pSource;
345+
346+
varinfo_t *pInfo = &pSrc->info;
301347
V_memset( pInfo, 0, sizeof( varinfo_t ) );
302348

303349
pInfo->isNotNetworked = !bNetworked;
@@ -311,17 +357,17 @@ class CScriptNetPropManager
311357

312358
varinfo_t* CacheFetch( CBaseEntity *pEnt, const char *szProp )
313359
{
314-
int idx = m_EntMap.Find( GetClassID( pEnt ) );
315-
if ( idx == m_EntMap.InvalidIndex() )
316-
return NULL;
360+
int idx = m_VarDicts.Find( szProp );
361+
if ( idx != m_VarDicts.InvalidIndex() )
362+
{
363+
vardictelem_t *pElem = &m_VarDicts.Element( idx );
364+
varsource_t *pSrc = CacheFind( pEnt, pElem );
317365

318-
vardict_t &dict = m_VarDicts.Element( idx );
319-
idx = dict.Find( szProp );
320-
if ( idx == dict.InvalidIndex() )
321-
return NULL;
366+
if ( pSrc )
367+
return &pSrc->info;
368+
}
322369

323-
varinfo_t *pInfo = &dict.Element( idx );
324-
return pInfo;
370+
return NULL;
325371
}
326372

327373
public:
@@ -332,7 +378,6 @@ class CScriptNetPropManager
332378

333379
void PurgeCache()
334380
{
335-
m_EntMap.Purge();
336381
m_VarDicts.Purge();
337382
}
338383

@@ -497,7 +542,7 @@ class CScriptNetPropManager
497542
{
498543

499544
#define SetVarInfo()\
500-
varinfo_t *pInfo = CacheNew( pEnt, szProp, true );\
545+
varinfo_t *pInfo = CacheNew( pEnt, szProp, (void*)pTable, true );\
501546
Assert( pProp->GetElementStride() <= VARINFO_ELEMSIZE_MAX );\
502547
pInfo->elemsize = pProp->GetElementStride();\
503548
Assert( pProp->GetNumElements() > 0 && pProp->GetNumElements() <= VARINFO_ARRAYSIZE_MAX );\
@@ -644,7 +689,7 @@ class CScriptNetPropManager
644689
{
645690
if ( IsEHandle( pProp ) )
646691
{
647-
varinfo_t *pInfo = CacheNew( pEnt, szProp, true );
692+
varinfo_t *pInfo = CacheNew( pEnt, szProp, (void*)pTable, true );
648693
pInfo->elemsize = sizeof(int);
649694
Assert( pArray->GetNumProps() > 0 && pArray->GetNumProps() <= VARINFO_ARRAYSIZE_MAX );
650695
pInfo->arraysize = pArray->GetNumProps();
@@ -661,7 +706,7 @@ class CScriptNetPropManager
661706
if ( size == 0 )
662707
break;
663708
#endif
664-
varinfo_t *pInfo = CacheNew( pEnt, szProp, true );
709+
varinfo_t *pInfo = CacheNew( pEnt, szProp, (void*)pTable, true );
665710

666711
if ( pArray->GetNumProps() > 1 )
667712
{
@@ -683,7 +728,7 @@ class CScriptNetPropManager
683728
}
684729
case DPT_Float:
685730
{
686-
varinfo_t *pInfo = CacheNew( pEnt, szProp, true );
731+
varinfo_t *pInfo = CacheNew( pEnt, szProp, (void*)pTable, true );
687732
pInfo->elemsize = sizeof(float);
688733
Assert( pArray->GetNumProps() > 0 && pArray->GetNumProps() <= VARINFO_ARRAYSIZE_MAX );
689734
pInfo->arraysize = pArray->GetNumProps();
@@ -693,7 +738,7 @@ class CScriptNetPropManager
693738
}
694739
case DPT_Vector:
695740
{
696-
varinfo_t *pInfo = CacheNew( pEnt, szProp, true );
741+
varinfo_t *pInfo = CacheNew( pEnt, szProp, (void*)pTable, true );
697742
pInfo->elemsize = sizeof(float)*3;
698743
Assert( pArray->GetNumProps() > 0 && pArray->GetNumProps() <= VARINFO_ARRAYSIZE_MAX );
699744
pInfo->arraysize = pArray->GetNumProps();
@@ -703,7 +748,7 @@ class CScriptNetPropManager
703748
}
704749
case DPT_VectorXY:
705750
{
706-
varinfo_t *pInfo = CacheNew( pEnt, szProp, true );
751+
varinfo_t *pInfo = CacheNew( pEnt, szProp, (void*)pTable, true );
707752
pInfo->elemsize = sizeof(float)*2;
708753
Assert( pArray->GetNumProps() > 0 && pArray->GetNumProps() <= VARINFO_ARRAYSIZE_MAX );
709754
pInfo->arraysize = pArray->GetNumProps();
@@ -829,7 +874,7 @@ class CScriptNetPropManager
829874
}
830875

831876
#define SetVarInfo()\
832-
varinfo_t *pInfo = CacheNew( pEnt, szProp, false );\
877+
varinfo_t *pInfo = CacheNew( pEnt, szProp, (void*)map, false );\
833878
Assert( pField->fieldSizeInBytes / pField->fieldSize <= VARINFO_ELEMSIZE_MAX );\
834879
pInfo->elemsize = pField->fieldSizeInBytes / pField->fieldSize;\
835880
Assert( pField->fieldSize > 0 && pField->fieldSize <= VARINFO_ARRAYSIZE_MAX );\
@@ -973,7 +1018,7 @@ class CScriptNetPropManager
9731018
return NULL;
9741019
}
9751020

976-
varinfo_t *pInfo = CacheNew( pEnt, szProp, false );
1021+
varinfo_t *pInfo = CacheNew( pEnt, szProp, (void*)map, false );
9771022
pInfo->arraysize = 1;
9781023
pInfo->offset = offset;
9791024
pInfo->datatype = datatype;

0 commit comments

Comments
 (0)