@@ -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
327373public:
@@ -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