diff --git a/sp/src/game/shared/mapbase/vscript_singletons.cpp b/sp/src/game/shared/mapbase/vscript_singletons.cpp index 81459ebfcf8..5a039709242 100644 --- a/sp/src/game/shared/mapbase/vscript_singletons.cpp +++ b/sp/src/game/shared/mapbase/vscript_singletons.cpp @@ -74,22 +74,36 @@ extern ISaveRestoreOps* GetStdStringDataOps(); #ifdef GAME_DLL #define UTLVECTOR_DATAOPS( fieldType, dataType )\ CUtlVectorDataopsInstantiator< fieldType >::GetDataOps( (CUtlVector< dataType >*)0 ) - #define IS_EHANDLE_UTLVECTOR( td )\ - td->pSaveRestoreOps == UTLVECTOR_DATAOPS( FIELD_EHANDLE, CHandle< CBaseEntity > ) ||\ - td->pSaveRestoreOps == UTLVECTOR_DATAOPS( FIELD_EHANDLE, CHandle< CBaseFlex > ) ||\ - td->pSaveRestoreOps == UTLVECTOR_DATAOPS( FIELD_EHANDLE, CHandle< CBaseAnimating > ) ||\ - td->pSaveRestoreOps == UTLVECTOR_DATAOPS( FIELD_EHANDLE, CHandle< CBaseCombatWeapon > ) ||\ - td->pSaveRestoreOps == UTLVECTOR_DATAOPS( FIELD_EHANDLE, CHandle< CBasePlayer > ) ||\ - td->pSaveRestoreOps == UTLVECTOR_DATAOPS( FIELD_EHANDLE, CHandle< CAI_BaseNPC > ) ||\ - td->pSaveRestoreOps == UTLVECTOR_DATAOPS( FIELD_EHANDLE, CHandle< CSceneEntity > ) ||\ - td->pSaveRestoreOps == UTLVECTOR_DATAOPS( FIELD_EHANDLE, CHandle< CSceneListManager > ) ||\ - td->pSaveRestoreOps == UTLVECTOR_DATAOPS( FIELD_EHANDLE, CHandle< CRagdollBoogie > ) ||\ - td->pSaveRestoreOps == UTLVECTOR_DATAOPS( FIELD_EHANDLE, CHandle< CFish > ) ||\ - td->pSaveRestoreOps == UTLVECTOR_DATAOPS( FIELD_EHANDLE, CHandle< CVGuiScreen > ) class CSceneListManager; class CRagdollBoogie; class CFish; + + bool IS_EHANDLE_UTLVECTOR( const typedescription_t *td ) + { + // Different entity handles are compiled as unique types, thus return unique SaveRestoreOps + return ( td->pSaveRestoreOps == UTLVECTOR_DATAOPS( FIELD_EHANDLE, CHandle< CBaseEntity > ) || + // CSceneEntity::m_hActorList + td->pSaveRestoreOps == UTLVECTOR_DATAOPS( FIELD_EHANDLE, CHandle< CBaseFlex > ) || + // CTriggerSoundscape::m_spectators + td->pSaveRestoreOps == UTLVECTOR_DATAOPS( FIELD_EHANDLE, CHandle< CBasePlayer > ) || + // CAI_GoalEntity::m_actors + td->pSaveRestoreOps == UTLVECTOR_DATAOPS( FIELD_EHANDLE, CHandle< CAI_BaseNPC > ) || + // CAntlionTemplateMaker::m_Children + //td->pSaveRestoreOps == UTLVECTOR_DATAOPS( FIELD_EHANDLE, CHandle< CNPC_Antlion > ) || + // CPointRagdollBoogie::m_Boogies + td->pSaveRestoreOps == UTLVECTOR_DATAOPS( FIELD_EHANDLE, CHandle< CRagdollBoogie > ) || + // CFishPool::m_fishes + td->pSaveRestoreOps == UTLVECTOR_DATAOPS( FIELD_EHANDLE, CHandle< CFish > ) || + // CBaseViewModel::m_hScreens + td->pSaveRestoreOps == UTLVECTOR_DATAOPS( FIELD_EHANDLE, CHandle< CVGuiScreen > ) || + // CSceneManager::{m_ActiveScenes, m_hNotifySceneCompletion} + td->pSaveRestoreOps == UTLVECTOR_DATAOPS( FIELD_EHANDLE, CHandle< CSceneEntity > ) || + // CSceneManager::m_hListManagers, CSceneListManager::m_hListManagers + td->pSaveRestoreOps == UTLVECTOR_DATAOPS( FIELD_EHANDLE, CHandle< CSceneListManager > ) + ); + } + #ifdef _DEBUG class CStringTableSaveRestoreOps; extern CStringTableSaveRestoreOps g_VguiScreenStringOps; @@ -160,7 +174,7 @@ class CScriptNetPropManager return 8; if ( proxy == RecvProxy_Int32ToInt16 ) return 16; - if ( proxy == RecvProxy_Int32ToInt32 ) + if ( proxy == RecvProxy_Int32ToInt32 || proxy == RecvProxy_IntToColor32 ) return 32; return 0; @@ -218,7 +232,14 @@ class CScriptNetPropManager #define MASK_INT_SIZE( _size ) ( ( 1 << (_size - 1) ) | ( (1 << (_size - 1)) - 1 ) ) #define MASK_NEAREST_BYTE( _bits ) ( ( (1 << ALIGN_TO_NEAREST_BYTE(_bits)) - 1 ) & ~((1 << _bits) - 1) ) #define ALIGN_TO_NEAREST_BYTE( _bits ) ( (_bits + 7) & ~7 ) - #define VARINFO_ARRAYSIZE_BITS 12 + #define VARINFO_ELEMSIZE_BITS 8 + #define VARINFO_ARRAYSIZE_BITS 16 + #define VARINFO_ELEMSIZE_MAX ( ( 1 << VARINFO_ELEMSIZE_BITS ) - 1 ) + #define VARINFO_ARRAYSIZE_MAX ( ( 1 << VARINFO_ARRAYSIZE_BITS ) - 1 ) + + // Else either clamp 'arraysize' assignments to 0x7fffffff + // or change unsigned boundary checks + COMPILE_TIME_ASSERT( VARINFO_ARRAYSIZE_BITS < 32 ); struct varinfo_t { @@ -232,13 +253,15 @@ class CScriptNetPropManager enum types datatype : 16; - // element size in bytes - unsigned int elemsize : 8; unsigned int arraysize : VARINFO_ARRAYSIZE_BITS; + // element size in bytes + unsigned int elemsize : VARINFO_ELEMSIZE_BITS; // Following are only used in integer netprops to handle unsigned and size casting - bool isUnsigned : 1; - bool isNotNetworked : 1; + unsigned int isUnsigned : 1; + unsigned int isNotNetworked : 1; + + unsigned int isGameRules : 1; int GetOffset( int index ) { @@ -258,7 +281,7 @@ class CScriptNetPropManager CUtlVector< int > m_EntMap; CUtlVector< vardict_t > m_VarDicts; - varinfo_t* CacheNew( CBaseEntity *pEnt, const char *szProp ) + varinfo_t *CacheNew( CBaseEntity *pEnt, const char *szProp, bool bNetworked ) { int idx = m_EntMap.Find( GetClassID( pEnt ) ); if ( idx == m_EntMap.InvalidIndex() ) @@ -276,6 +299,13 @@ class CScriptNetPropManager varinfo_t *pInfo = &dict.Element( idx ); V_memset( pInfo, 0, sizeof( varinfo_t ) ); + + pInfo->isNotNetworked = !bNetworked; + + // see Recv/SendProxy_HL2GameRules + if ( bNetworked && dynamic_cast< CGameRulesProxy* >( pEnt ) ) + pInfo->isGameRules = 1; + return pInfo; } @@ -458,7 +488,7 @@ class CScriptNetPropManager // Searches NetTable first to handle overwritten member network variables - see // CPlayerResource::m_iHealth and CBaseEntity::m_iHealth - varinfo_t *GetVarInfo( CBaseEntity *pEnt, const char *szProp, int index ) + varinfo_t *GetVarInfo( CBaseEntity *pEnt, const char *szProp, int index, bool bDontWarnOnMissing = false ) { int offset = 0; NetTable *pTable = GetNetTable( GetNetworkClass( pEnt ) ); @@ -467,9 +497,10 @@ class CScriptNetPropManager { #define SetVarInfo()\ - varinfo_t *pInfo = CacheNew( pEnt, szProp );\ - pInfo->isNotNetworked = 0;\ + varinfo_t *pInfo = CacheNew( pEnt, szProp, true );\ + Assert( pProp->GetElementStride() <= VARINFO_ELEMSIZE_MAX );\ pInfo->elemsize = pProp->GetElementStride();\ + Assert( pProp->GetNumElements() > 0 && pProp->GetNumElements() <= VARINFO_ARRAYSIZE_MAX );\ pInfo->arraysize = pProp->GetNumElements();\ pInfo->offset = offset; @@ -613,8 +644,9 @@ class CScriptNetPropManager { if ( IsEHandle( pProp ) ) { - varinfo_t *pInfo = CacheNew( pEnt, szProp ); + varinfo_t *pInfo = CacheNew( pEnt, szProp, true ); pInfo->elemsize = sizeof(int); + Assert( pArray->GetNumProps() > 0 && pArray->GetNumProps() <= VARINFO_ARRAYSIZE_MAX ); pInfo->arraysize = pArray->GetNumProps(); pInfo->offset = offset; pInfo->datatype = types::_EHANDLE; @@ -629,7 +661,7 @@ class CScriptNetPropManager if ( size == 0 ) break; #endif - varinfo_t *pInfo = CacheNew( pEnt, szProp ); + varinfo_t *pInfo = CacheNew( pEnt, szProp, true ); if ( pArray->GetNumProps() > 1 ) { @@ -641,6 +673,7 @@ class CScriptNetPropManager pInfo->elemsize = 0; } + Assert( pArray->GetNumProps() > 0 && pArray->GetNumProps() <= VARINFO_ARRAYSIZE_MAX ); pInfo->arraysize = pArray->GetNumProps(); pInfo->offset = offset; pInfo->mask = MASK_INT_SIZE( size ); @@ -650,8 +683,9 @@ class CScriptNetPropManager } case DPT_Float: { - varinfo_t *pInfo = CacheNew( pEnt, szProp ); + varinfo_t *pInfo = CacheNew( pEnt, szProp, true ); pInfo->elemsize = sizeof(float); + Assert( pArray->GetNumProps() > 0 && pArray->GetNumProps() <= VARINFO_ARRAYSIZE_MAX ); pInfo->arraysize = pArray->GetNumProps(); pInfo->offset = offset; pInfo->datatype = types::_FLOAT; @@ -659,8 +693,9 @@ class CScriptNetPropManager } case DPT_Vector: { - varinfo_t *pInfo = CacheNew( pEnt, szProp ); + varinfo_t *pInfo = CacheNew( pEnt, szProp, true ); pInfo->elemsize = sizeof(float)*3; + Assert( pArray->GetNumProps() > 0 && pArray->GetNumProps() <= VARINFO_ARRAYSIZE_MAX ); pInfo->arraysize = pArray->GetNumProps(); pInfo->offset = offset; pInfo->datatype = types::_VEC3; @@ -668,8 +703,9 @@ class CScriptNetPropManager } case DPT_VectorXY: { - varinfo_t *pInfo = CacheNew( pEnt, szProp ); + varinfo_t *pInfo = CacheNew( pEnt, szProp, true ); pInfo->elemsize = sizeof(float)*2; + Assert( pArray->GetNumProps() > 0 && pArray->GetNumProps() <= VARINFO_ARRAYSIZE_MAX ); pInfo->arraysize = pArray->GetNumProps(); pInfo->offset = offset; pInfo->datatype = types::_VEC2; @@ -793,9 +829,10 @@ class CScriptNetPropManager } #define SetVarInfo()\ - varinfo_t *pInfo = CacheNew( pEnt, szProp );\ - pInfo->isNotNetworked = 1;\ + varinfo_t *pInfo = CacheNew( pEnt, szProp, false );\ + Assert( pField->fieldSizeInBytes / pField->fieldSize <= VARINFO_ELEMSIZE_MAX );\ pInfo->elemsize = pField->fieldSizeInBytes / pField->fieldSize;\ + Assert( pField->fieldSize > 0 && pField->fieldSize <= VARINFO_ARRAYSIZE_MAX );\ pInfo->arraysize = pField->fieldSize;\ pInfo->offset = offset; @@ -812,7 +849,6 @@ class CScriptNetPropManager { SetVarInfo(); pInfo->isUnsigned = ( pField->flags & SPROP_UNSIGNED ) != 0; - pInfo->isNotNetworked = 1; switch ( pField->fieldType ) { case FIELD_INTEGER: @@ -904,26 +940,26 @@ class CScriptNetPropManager else if ( IS_EHANDLE_UTLVECTOR( pField ) ) { SetVarInfo(); - pInfo->arraysize = ( 1 << VARINFO_ARRAYSIZE_BITS ) - 1; // dynamic, check on get + pInfo->arraysize = VARINFO_ARRAYSIZE_MAX; pInfo->datatype = types::_DAR_EHANDLE; } else if ( pField->pSaveRestoreOps == UTLVECTOR_DATAOPS( FIELD_CLASSPTR, CBaseEntity* ) ) { SetVarInfo(); - pInfo->arraysize = ( 1 << VARINFO_ARRAYSIZE_BITS ) - 1; // dynamic, check on get + pInfo->arraysize = VARINFO_ARRAYSIZE_MAX; pInfo->datatype = types::_DAR_CLASSPTR; } else if ( pField->pSaveRestoreOps == UTLVECTOR_DATAOPS( FIELD_INTEGER, int ) ) { SetVarInfo(); - pInfo->arraysize = ( 1 << VARINFO_ARRAYSIZE_BITS ) - 1; // dynamic, check on get + pInfo->arraysize = VARINFO_ARRAYSIZE_MAX; pInfo->datatype = types::_DAR_INT; } else if ( pField->pSaveRestoreOps == UTLVECTOR_DATAOPS( FIELD_FLOAT, float ) || pField->pSaveRestoreOps == UTLVECTOR_DATAOPS( FIELD_TIME, float ) ) { SetVarInfo(); - pInfo->arraysize = ( 1 << VARINFO_ARRAYSIZE_BITS ) - 1; // dynamic, check on get + pInfo->arraysize = VARINFO_ARRAYSIZE_MAX; pInfo->datatype = types::_DAR_FLOAT; } // Only used by CAI_PlayerAlly::m_PendingConcept @@ -956,9 +992,21 @@ class CScriptNetPropManager } } #endif + + if ( !bDontWarnOnMissing ) + Warning( "NetProp field (%s)->'%s' does not exist!\n", pEnt->GetClassname(), szProp ); + return NULL; } + char *GetBase( CBaseEntity *pEnt, const varinfo_t *pInfo ) + { + if ( pInfo->isGameRules ) + return (char*)GameRules(); + + return (char*)pEnt; + } + public: // FIXME: Cannot get datatable/arrays at the moment bool HasProp( HSCRIPT hEnt, const char *szProp ) @@ -970,7 +1018,7 @@ class CScriptNetPropManager varinfo_t *pInfo = CacheFetch( pEnt, szProp ); if ( !pInfo ) { - pInfo = GetVarInfo( pEnt, szProp, INDEX_GET_TYPE ); + pInfo = GetVarInfo( pEnt, szProp, INDEX_GET_TYPE, true ); if ( !pInfo ) return false; @@ -1044,33 +1092,36 @@ class CScriptNetPropManager if ( !pInfo ) return -1; } + #ifdef GAME_DLL + char *pBase = GetBase( pEnt, pInfo ); + switch ( pInfo->datatype ) { case types::_DAR_EHANDLE: { - CUtlVector< EHANDLE > &vec = *(CUtlVector< EHANDLE >*)((char*)pEnt + pInfo->offset); + CUtlVector< EHANDLE > &vec = *(CUtlVector< EHANDLE >*)(pBase + pInfo->offset); if ( !vec.Base() ) return -1; return vec.Count(); } case types::_DAR_CLASSPTR: { - CUtlVector< CBaseEntity* > &vec = *(CUtlVector< CBaseEntity* >*)((char*)pEnt + pInfo->offset); + CUtlVector< CBaseEntity* > &vec = *(CUtlVector< CBaseEntity* >*)(pBase + pInfo->offset); if ( !vec.Base() ) return -1; return vec.Count(); } case types::_DAR_INT: { - CUtlVector< int > &vec = *(CUtlVector< int >*)((char*)pEnt + pInfo->offset); + CUtlVector< int > &vec = *(CUtlVector< int >*)(pBase + pInfo->offset); if ( !vec.Base() ) return -1; return vec.Count(); } case types::_DAR_FLOAT: { - CUtlVector< float > &vec = *(CUtlVector< float >*)((char*)pEnt + pInfo->offset); + CUtlVector< float > &vec = *(CUtlVector< float >*)(pBase + pInfo->offset); if ( !vec.Base() ) return -1; return vec.Count(); @@ -1096,7 +1147,7 @@ class CScriptNetPropManager return -1; } - if ( index < 0 || (unsigned int)index >= pInfo->arraysize ) + if ( (unsigned int)index >= pInfo->arraysize ) return -1; if ( pInfo->isNotNetworked ) @@ -1132,10 +1183,12 @@ class CScriptNetPropManager } else { + char *pBase = GetBase( pEnt, pInfo ); + switch ( pInfo->datatype ) { case types::_INT32: - return (*(int*)((char*)pEnt + pInfo->GetOffset( index ))) & pInfo->mask; + return (*(int*)(pBase + pInfo->GetOffset( index ))) & pInfo->mask; } } @@ -1157,7 +1210,7 @@ class CScriptNetPropManager return; } - if ( index < 0 || (unsigned int)index >= pInfo->arraysize ) + if ( (unsigned int)index >= pInfo->arraysize ) return; if ( pInfo->isNotNetworked ) @@ -1215,11 +1268,13 @@ class CScriptNetPropManager } else { + char *pBase = GetBase( pEnt, pInfo ); + switch ( pInfo->datatype ) { case types::_INT32: { - int *dest = (int*)((char*)pEnt + pInfo->GetOffset( index )); + int *dest = (int*)(pBase + pInfo->GetOffset( index )); *dest = (*dest & ~pInfo->mask) | (value & pInfo->mask); NetworkStateChanged( pEnt, pInfo->GetOffset( index ) ); break; @@ -1248,19 +1303,21 @@ class CScriptNetPropManager if ( pInfo->datatype == types::_VEC3 ) arraysize *= 3; - if ( index < 0 || (unsigned int)index >= arraysize ) + if ( (unsigned int)index >= arraysize ) return -1; + char *pBase = GetBase( pEnt, pInfo ); + switch ( pInfo->datatype ) { case types::_FLOAT: - return *(float*)((char*)pEnt + pInfo->GetOffset( index )); + return *(float*)(pBase + pInfo->GetOffset( index )); case types::_VEC3: - return ((float*)((char*)pEnt + pInfo->GetOffset( index / 3 )))[ index % 3 ]; + return ((float*)(pBase + pInfo->GetOffset( index / 3 )))[ index % 3 ]; #ifdef GAME_DLL case types::_DAR_FLOAT: { - CUtlVector< float > &vec = *(CUtlVector< float >*)((char*)pEnt + pInfo->offset); + CUtlVector< float > &vec = *(CUtlVector< float >*)(pBase + pInfo->offset); if ( !vec.Base() ) return -1; if ( index >= vec.Count() ) @@ -1293,23 +1350,25 @@ class CScriptNetPropManager if ( pInfo->datatype == types::_VEC3 ) arraysize *= 3; - if ( index < 0 || (unsigned int)index >= arraysize ) + if ( (unsigned int)index >= arraysize ) return; + char *pBase = GetBase( pEnt, pInfo ); + switch ( pInfo->datatype ) { case types::_FLOAT: - *(float*)((char*)pEnt + pInfo->GetOffset( index )) = value; + *(float*)(pBase + pInfo->GetOffset( index )) = value; NetworkStateChanged( pEnt, pInfo->GetOffset( index ) ); break; case types::_VEC3: - ((float*)((char*)pEnt + pInfo->GetOffset( index / 3 )))[ index % 3 ] = value; + ((float*)(pBase + pInfo->GetOffset( index / 3 )))[ index % 3 ] = value; NetworkStateChanged( pEnt, pInfo->GetOffset( index / 3 ) ); break; #ifdef GAME_DLL case types::_DAR_FLOAT: { - CUtlVector< float > &vec = *(CUtlVector< float >*)((char*)pEnt + pInfo->offset); + CUtlVector< float > &vec = *(CUtlVector< float >*)(pBase + pInfo->offset); if ( !vec.Base() ) return; if ( index >= vec.Count() ) @@ -1337,30 +1396,32 @@ class CScriptNetPropManager return NULL; } - if ( index < 0 || (unsigned int)index >= pInfo->arraysize ) + if ( (unsigned int)index >= pInfo->arraysize ) return NULL; + char *pBase = GetBase( pEnt, pInfo ); + switch ( pInfo->datatype ) { case types::_EHANDLE: { - EHANDLE &iEHandle = *(EHANDLE*)((char*)pEnt + pInfo->GetOffset( index )); + EHANDLE &iEHandle = *(EHANDLE*)(pBase + pInfo->GetOffset( index )); return ToHScript( iEHandle ); } #ifdef GAME_DLL case types::_CLASSPTR: { - CBaseEntity* ptr = *(CBaseEntity**)((char*)pEnt + pInfo->GetOffset( index )); + CBaseEntity *ptr = *(CBaseEntity**)(pBase + pInfo->GetOffset( index )); return ToHScript( ptr ); } case types::_EDICT: { - edict_t* ptr = *(edict_t**)((char*)pEnt + pInfo->GetOffset( index )); + edict_t *ptr = *(edict_t**)(pBase + pInfo->GetOffset( index )); return ToHScript( GetContainingEntity( ptr ) ); } case types::_DAR_EHANDLE: { - CUtlVector< EHANDLE > &vec = *(CUtlVector< EHANDLE >*)((char*)pEnt + pInfo->offset); + CUtlVector< EHANDLE > &vec = *(CUtlVector< EHANDLE >*)(pBase + pInfo->offset); if ( !vec.Base() ) return NULL; if ( index >= vec.Count() ) @@ -1369,7 +1430,7 @@ class CScriptNetPropManager } case types::_DAR_CLASSPTR: { - CUtlVector< CBaseEntity* > &vec = *(CUtlVector< CBaseEntity* >*)((char*)pEnt + pInfo->offset); + CUtlVector< CBaseEntity* > &vec = *(CUtlVector< CBaseEntity* >*)(pBase + pInfo->offset); if ( !vec.Base() ) return NULL; if ( index >= vec.Count() ) @@ -1379,7 +1440,7 @@ class CScriptNetPropManager #endif case types::_PHYS: { - IPhysicsObject* ptr = *(IPhysicsObject**)((char*)pEnt + pInfo->GetOffset( index )); + IPhysicsObject *ptr = *(IPhysicsObject**)(pBase + pInfo->GetOffset( index )); return ptr ? g_pScriptVM->RegisterInstance( ptr ) : NULL; } } @@ -1402,30 +1463,32 @@ class CScriptNetPropManager return; } - if ( index < 0 || (unsigned int)index >= pInfo->arraysize ) + if ( (unsigned int)index >= pInfo->arraysize ) return; + char *pBase = GetBase( pEnt, pInfo ); + switch ( pInfo->datatype ) { case types::_EHANDLE: - *(EHANDLE*)((char*)pEnt + pInfo->GetOffset( index )) = ToEnt( value ); + *(EHANDLE*)(pBase + pInfo->GetOffset( index )) = ToEnt( value ); NetworkStateChanged( pEnt, pInfo->GetOffset( index ) ); break; #ifdef GAME_DLL case types::_CLASSPTR: - *(CBaseEntity**)((char*)pEnt + pInfo->GetOffset( index )) = ToEnt( value ); + *(CBaseEntity**)(pBase + pInfo->GetOffset( index )) = ToEnt( value ); NetworkStateChanged( pEnt, pInfo->GetOffset( index ) ); break; case types::_EDICT: { CBaseEntity* ptr = ToEnt( value ); - *(edict_t**)((char*)pEnt + pInfo->GetOffset( index )) = ptr ? ptr->edict() : NULL; + *(edict_t**)(pBase + pInfo->GetOffset( index )) = ptr ? ptr->edict() : NULL; NetworkStateChanged( pEnt, pInfo->GetOffset( index ) ); break; } case types::_DAR_EHANDLE: { - CUtlVector< EHANDLE > &vec = *(CUtlVector< EHANDLE >*)((char*)pEnt + pInfo->offset); + CUtlVector< EHANDLE > &vec = *(CUtlVector< EHANDLE >*)(pBase + pInfo->offset); if ( !vec.Base() ) return; if ( index >= vec.Count() ) @@ -1436,7 +1499,7 @@ class CScriptNetPropManager } case types::_DAR_CLASSPTR: { - CUtlVector< CBaseEntity* > &vec = *(CUtlVector< CBaseEntity* >*)((char*)pEnt + pInfo->offset); + CUtlVector< CBaseEntity* > &vec = *(CUtlVector< CBaseEntity* >*)(pBase + pInfo->offset); if ( !vec.Base() ) return; if ( index >= vec.Count() ) @@ -1464,13 +1527,15 @@ class CScriptNetPropManager return vec3_invalid; } - if ( index < 0 || (unsigned int)index >= pInfo->arraysize ) + if ( (unsigned int)index >= pInfo->arraysize ) return vec3_invalid; + char *pBase = GetBase( pEnt, pInfo ); + switch ( pInfo->datatype ) { case types::_VEC3: - return *(Vector*)((char*)pEnt + pInfo->GetOffset( index )); + return *(Vector*)(pBase + pInfo->GetOffset( index )); } return vec3_invalid; @@ -1491,13 +1556,15 @@ class CScriptNetPropManager return; } - if ( index < 0 || (unsigned int)index >= pInfo->arraysize ) + if ( (unsigned int)index >= pInfo->arraysize ) return; + char *pBase = GetBase( pEnt, pInfo ); + switch ( pInfo->datatype ) { case types::_VEC3: - *(Vector*)((char*)pEnt + pInfo->GetOffset( index )) = value; + *(Vector*)(pBase + pInfo->GetOffset( index )) = value; NetworkStateChanged( pEnt, pInfo->GetOffset( index ) ); break; } @@ -1518,21 +1585,23 @@ class CScriptNetPropManager return NULL; } - if ( index < 0 || (unsigned int)index >= pInfo->arraysize ) + if ( (unsigned int)index >= pInfo->arraysize ) return NULL; + char *pBase = GetBase( pEnt, pInfo ); + switch ( pInfo->datatype ) { case types::_CSTRING: - return (const char*)((char*)pEnt + pInfo->GetOffset( index )); + return (const char*)(pBase + pInfo->GetOffset( index )); case types::_STRING_T: // Identical to _CSTRING on client - return STRING( *(string_t*)((char*)pEnt + pInfo->GetOffset( index )) ); + return STRING( *(string_t*)(pBase + pInfo->GetOffset( index )) ); case types::_INT8: { if ( !pInfo->stringsize ) return NULL; - char * const pVar = ((char*)pEnt + pInfo->GetOffset( index )); + char * const pVar = pBase + pInfo->GetOffset( index ); // Is this null terminated? int i = 0; @@ -1550,7 +1619,7 @@ class CScriptNetPropManager } #ifdef GAME_DLL case types::_STDSTRING: - return ( (std::string*)((char*)pEnt + pInfo->GetOffset( index )) )->c_str(); + return ( (std::string*)(pBase + pInfo->GetOffset( index )) )->c_str(); #endif } @@ -1572,9 +1641,11 @@ class CScriptNetPropManager return; } - if ( index < 0 || (unsigned int)index >= pInfo->arraysize ) + if ( (unsigned int)index >= pInfo->arraysize ) return; + char *pBase = GetBase( pEnt, pInfo ); + switch ( pInfo->datatype ) { case types::_CSTRING: @@ -1582,7 +1653,7 @@ class CScriptNetPropManager { if ( pInfo->stringsize ) { - V_strncpy( (char*)pEnt + pInfo->GetOffset( index ), value, pInfo->stringsize ); + V_strncpy( pBase + pInfo->GetOffset( index ), value, pInfo->stringsize ); NetworkStateChanged( pEnt, pInfo->GetOffset( index ) ); break; } @@ -1596,9 +1667,9 @@ class CScriptNetPropManager if ( src == NULL_STRING ) src = AllocPooledString( value ); #ifdef GAME_DLL - *(string_t*)((char*)pEnt + pInfo->GetOffset( index )) = src; + *(string_t*)(pBase + pInfo->GetOffset( index )) = src; #else - V_strcpy( (char*)pEnt + pInfo->GetOffset( index ), src ); + V_strcpy( pBase + pInfo->GetOffset( index ), src ); #endif NetworkStateChanged( pEnt, pInfo->GetOffset( index ) ); break; @@ -1606,7 +1677,7 @@ class CScriptNetPropManager #ifdef GAME_DLL case types::_STDSTRING: { - ( (std::string*)((char*)pEnt + pInfo->GetOffset( index )) )->assign( value, V_strlen(value) ); + ( (std::string*)(pBase + pInfo->GetOffset( index )) )->assign( value, V_strlen(value) ); NetworkStateChanged( pEnt, pInfo->GetOffset( index ) ); break; } @@ -1884,7 +1955,6 @@ class CScriptNetPropManager case DPT_DataTable: { NetTable* pArray = pProp->GetDataTable(); - Assert( pArray->GetNumProps() ); if ( V_strcmp( pProp->GetName(), pArray->GetName() ) != 0 ) { @@ -1893,6 +1963,8 @@ class CScriptNetPropManager break; } + Assert( pArray->GetNumProps() > 0 && pArray->GetNumProps() <= VARINFO_ARRAYSIZE_MAX ); + // Double check that each element is the same size // Array indexing ints gets element size from this int diff1 = pArray->GetProp(1)->GetOffset() - pArray->GetProp(0)->GetOffset(); @@ -1925,6 +1997,9 @@ class CScriptNetPropManager NetProp *pArray = pProp->GetArrayProp(); pVar += pArray->GetOffset(); + Assert( pProp->GetNumElements() > 0 && pProp->GetNumElements() <= VARINFO_ARRAYSIZE_MAX ); + Assert( pProp->GetElementStride() <= VARINFO_ELEMSIZE_MAX ); + int numElements = pProp->GetNumElements(); int elementStride = pProp->GetElementStride(); @@ -2210,13 +2285,17 @@ class CScriptNetPropManager Print("null"); return; } + + Assert( vec.Count() >= 0 && vec.Count() <= VARINFO_ARRAYSIZE_MAX ); Print("\n%s[", m_indent.Get()); Indent1(); + FOR_EACH_VEC( vec, i ) { Print("\n%s", m_indent.Get()); PrintEntity( vec[i] ); } + Indent0(); Print("\n%s]", m_indent.Get()); } @@ -2228,13 +2307,17 @@ class CScriptNetPropManager Print("null"); return; } + + Assert( vec.Count() >= 0 && vec.Count() <= VARINFO_ARRAYSIZE_MAX ); Print("\n%s[", m_indent.Get()); Indent1(); + FOR_EACH_VEC( vec, i ) { Print("\n%s", m_indent.Get()); Print( "%i", vec[i] ); } + Indent0(); Print("\n%s]", m_indent.Get()); } @@ -2247,13 +2330,17 @@ class CScriptNetPropManager Print("null"); return; } + + Assert( vec.Count() >= 0 && vec.Count() <= VARINFO_ARRAYSIZE_MAX ); Print("\n%s[", m_indent.Get()); Indent1(); + FOR_EACH_VEC( vec, i ) { Print("\n%s", m_indent.Get()); Print( "%f", vec[i] ); } + Indent0(); Print("\n%s]", m_indent.Get()); } @@ -2265,13 +2352,17 @@ class CScriptNetPropManager Print("null"); return; } + + Assert( vec.Count() >= 0 && vec.Count() <= VARINFO_ARRAYSIZE_MAX ); Print("\n%s[", m_indent.Get()); Indent1(); + FOR_EACH_VEC( vec, i ) { Print("\n%s", m_indent.Get()); PrintString( vec[i] ); } + Indent0(); Print("\n%s]", m_indent.Get()); } @@ -2283,13 +2374,17 @@ class CScriptNetPropManager Print("null"); return; } + + Assert( vec.Count() >= 0 && vec.Count() <= VARINFO_ARRAYSIZE_MAX ); Print("\n%s[", m_indent.Get()); Indent1(); + FOR_EACH_VEC( vec, i ) { Print("\n%s", m_indent.Get()); PrintEntity( vec[i] ); } + Indent0(); Print("\n%s]", m_indent.Get()); } @@ -2444,6 +2539,9 @@ class CScriptNetPropManager } else { + Assert( td->fieldSize > 0 && td->fieldSize <= VARINFO_ARRAYSIZE_MAX ); + Assert( td->fieldSizeInBytes / td->fieldSize <= VARINFO_ELEMSIZE_MAX ); + Print(" <"); PrintFieldType( pVar, td ); Print(" array> #%d", td->fieldSize); @@ -2492,9 +2590,11 @@ class CScriptNetPropManager m_output.SetBufferType( true, false ); IndentStart(); + void *pNetBase = dynamic_cast< CGameRulesProxy* >( pEnt ) ? (void*)GameRules() : (void*)pEnt; + Print( "\n" ); Print( "(%s)\n", GetNetTable( GetNetworkClass(pEnt) )->GetName() ); - DumpNetTable_r( pEnt, GetNetTable( GetNetworkClass(pEnt) ) ); + DumpNetTable_r( pNetBase, GetNetTable( GetNetworkClass(pEnt) ) ); Print( "\n\n" ); Print( "\n" );