Team Fortress 2 Source Code as on 22/4/2020
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

3440 lines
89 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose: Helper classes and functions for the save/restore system.
  4. //
  5. // $NoKeywords: $
  6. //=============================================================================//
  7. #include "cbase.h"
  8. #include <limits.h>
  9. #include "isaverestore.h"
  10. #include "saverestore.h"
  11. #include <stdarg.h>
  12. #include "shake.h"
  13. #include "decals.h"
  14. #include "gamerules.h"
  15. #include "bspfile.h"
  16. #include "mathlib/mathlib.h"
  17. #include "engine/IEngineSound.h"
  18. #include "saverestoretypes.h"
  19. #include "saverestore_utlvector.h"
  20. #include "model_types.h"
  21. #include "igamesystem.h"
  22. #include "interval.h"
  23. #include "vphysics/object_hash.h"
  24. #include "datacache/imdlcache.h"
  25. #include "tier0/vprof.h"
  26. #if !defined( CLIENT_DLL )
  27. #include "globalstate.h"
  28. #include "entitylist.h"
  29. #else
  30. #include "gamestringpool.h"
  31. #endif
  32. // HACKHACK: Builds a global list of entities that were restored from all levels
  33. #if !defined( CLIENT_DLL )
  34. void AddRestoredEntity( CBaseEntity *pEntity );
  35. #else
  36. void AddRestoredEntity( C_BaseEntity *pEntity );
  37. #endif
  38. // memdbgon must be the last include file in a .cpp file!!!
  39. #include "tier0/memdbgon.h"
  40. #define MAX_ENTITYARRAY 1024
  41. #define ZERO_TIME ((FLT_MAX*-0.5))
  42. // A bit arbitrary, but unlikely to collide with any saved games...
  43. #define TICK_NEVER_THINK_ENCODE ( INT_MAX - 3 )
  44. ASSERT_INVARIANT( sizeof(EHandlePlaceholder_t) == sizeof(EHANDLE) );
  45. //-----------------------------------------------------------------------------
  46. static int gSizes[FIELD_TYPECOUNT] =
  47. {
  48. FIELD_SIZE( FIELD_VOID ),
  49. FIELD_SIZE( FIELD_FLOAT ),
  50. FIELD_SIZE( FIELD_STRING ),
  51. FIELD_SIZE( FIELD_VECTOR ),
  52. FIELD_SIZE( FIELD_QUATERNION ),
  53. FIELD_SIZE( FIELD_INTEGER ),
  54. FIELD_SIZE( FIELD_BOOLEAN ),
  55. FIELD_SIZE( FIELD_SHORT ),
  56. FIELD_SIZE( FIELD_CHARACTER ),
  57. FIELD_SIZE( FIELD_COLOR32 ),
  58. FIELD_SIZE( FIELD_EMBEDDED ),
  59. FIELD_SIZE( FIELD_CUSTOM ),
  60. FIELD_SIZE( FIELD_CLASSPTR ),
  61. FIELD_SIZE( FIELD_EHANDLE ),
  62. FIELD_SIZE( FIELD_EDICT ),
  63. FIELD_SIZE( FIELD_POSITION_VECTOR ),
  64. FIELD_SIZE( FIELD_TIME ),
  65. FIELD_SIZE( FIELD_TICK ),
  66. FIELD_SIZE( FIELD_MODELNAME ),
  67. FIELD_SIZE( FIELD_SOUNDNAME ),
  68. FIELD_SIZE( FIELD_INPUT ),
  69. FIELD_SIZE( FIELD_FUNCTION ),
  70. FIELD_SIZE( FIELD_VMATRIX ),
  71. FIELD_SIZE( FIELD_VMATRIX_WORLDSPACE ),
  72. FIELD_SIZE( FIELD_MATRIX3X4_WORLDSPACE ),
  73. FIELD_SIZE( FIELD_INTERVAL ),
  74. FIELD_SIZE( FIELD_MODELINDEX ),
  75. FIELD_SIZE( FIELD_MATERIALINDEX ),
  76. FIELD_SIZE( FIELD_VECTOR2D ),
  77. };
  78. // helpers to offset worldspace matrices
  79. static void VMatrixOffset( VMatrix &dest, const VMatrix &matrixIn, const Vector &offset )
  80. {
  81. dest = matrixIn;
  82. dest.PostTranslate( offset );
  83. }
  84. static void Matrix3x4Offset( matrix3x4_t& dest, const matrix3x4_t& matrixIn, const Vector &offset )
  85. {
  86. MatrixCopy( matrixIn, dest );
  87. Vector out;
  88. MatrixGetColumn( matrixIn, 3, out );
  89. out += offset;
  90. MatrixSetColumn( out, 3, dest );
  91. }
  92. // This does the necessary casting / extract to grab a pointer to a member function as a void *
  93. // UNDONE: Cast to BASEPTR or something else here?
  94. #define EXTRACT_INPUTFUNC_FUNCTIONPTR(x) (*(inputfunc_t **)(&(x)))
  95. //-----------------------------------------------------------------------------
  96. // Purpose: Search this datamap for the name of this member function
  97. // This is used to save/restore function pointers (convert pointer to text)
  98. // Input : *function - pointer to member function
  99. // Output : const char * - function name
  100. //-----------------------------------------------------------------------------
  101. const char *UTIL_FunctionToName( datamap_t *pMap, inputfunc_t *function )
  102. {
  103. while ( pMap )
  104. {
  105. for ( int i = 0; i < pMap->dataNumFields; i++ )
  106. {
  107. if ( pMap->dataDesc[i].flags & FTYPEDESC_FUNCTIONTABLE )
  108. {
  109. #ifdef WIN32
  110. Assert( sizeof(pMap->dataDesc[i].inputFunc) == sizeof(void *) );
  111. #elif defined(POSIX)
  112. Assert( sizeof(pMap->dataDesc[i].inputFunc) == 8 );
  113. #else
  114. #error
  115. #endif
  116. inputfunc_t *pTest = EXTRACT_INPUTFUNC_FUNCTIONPTR(pMap->dataDesc[i].inputFunc);
  117. if ( pTest == function )
  118. return pMap->dataDesc[i].fieldName;
  119. }
  120. }
  121. pMap = pMap->baseMap;
  122. }
  123. return NULL;
  124. }
  125. //-----------------------------------------------------------------------------
  126. // Purpose: Search the datamap for a function named pName
  127. // This is used to save/restore function pointers (convert text back to pointer)
  128. // Input : *pName - name of the member function
  129. //-----------------------------------------------------------------------------
  130. inputfunc_t *UTIL_FunctionFromName( datamap_t *pMap, const char *pName )
  131. {
  132. while ( pMap )
  133. {
  134. for ( int i = 0; i < pMap->dataNumFields; i++ )
  135. {
  136. #ifdef WIN32
  137. Assert( sizeof(pMap->dataDesc[i].inputFunc) == sizeof(void *) );
  138. #elif defined(POSIX)
  139. Assert( sizeof(pMap->dataDesc[i].inputFunc) == 8 );
  140. #else
  141. #error
  142. #endif
  143. if ( pMap->dataDesc[i].flags & FTYPEDESC_FUNCTIONTABLE )
  144. {
  145. if ( FStrEq( pName, pMap->dataDesc[i].fieldName ) )
  146. {
  147. return EXTRACT_INPUTFUNC_FUNCTIONPTR(pMap->dataDesc[i].inputFunc);
  148. }
  149. }
  150. }
  151. pMap = pMap->baseMap;
  152. }
  153. Msg( "Failed to find function %s\n", pName );
  154. return NULL;
  155. }
  156. //-----------------------------------------------------------------------------
  157. //
  158. // CSave
  159. //
  160. //-----------------------------------------------------------------------------
  161. CSave::CSave( CSaveRestoreData *pdata )
  162. : m_pData(pdata),
  163. m_pGameInfo( pdata ),
  164. m_bAsync( pdata->bAsync )
  165. {
  166. m_BlockStartStack.EnsureCapacity( 32 );
  167. // Logging.
  168. m_hLogFile = NULL;
  169. }
  170. //-------------------------------------
  171. inline int CSave::DataEmpty( const char *pdata, int size )
  172. {
  173. if ( size != 4 )
  174. {
  175. const char *pLimit = pdata + size;
  176. while ( pdata < pLimit )
  177. {
  178. if ( *pdata++ )
  179. return 0;
  180. }
  181. return 1;
  182. }
  183. return ( *((int *)pdata) == 0 );
  184. }
  185. //-----------------------------------------------------------------------------
  186. // Purpose: Start logging save data.
  187. //-----------------------------------------------------------------------------
  188. void CSave::StartLogging( const char *pszLogName )
  189. {
  190. m_hLogFile = filesystem->Open( pszLogName, "w" );
  191. }
  192. //-----------------------------------------------------------------------------
  193. // Purpose: Stop logging save data.
  194. //-----------------------------------------------------------------------------
  195. void CSave::EndLogging( void )
  196. {
  197. if ( m_hLogFile )
  198. {
  199. filesystem->Close( m_hLogFile );
  200. }
  201. m_hLogFile = NULL;
  202. }
  203. //-----------------------------------------------------------------------------
  204. // Purpose: Check to see if we are logging data.
  205. //-----------------------------------------------------------------------------
  206. bool CSave::IsLogging( void )
  207. {
  208. return ( m_hLogFile != NULL );
  209. }
  210. //-----------------------------------------------------------------------------
  211. // Purpose: Log data.
  212. //-----------------------------------------------------------------------------
  213. void CSave::Log( const char *pName, fieldtype_t fieldType, void *value, int count )
  214. {
  215. // Check to see if we are logging.
  216. if ( !IsLogging() )
  217. return;
  218. static char szBuf[1024];
  219. static char szTempBuf[256];
  220. // Save the name.
  221. Q_snprintf( szBuf, sizeof( szBuf ), "%s ", pName );
  222. for ( int iCount = 0; iCount < count; ++iCount )
  223. {
  224. switch ( fieldType )
  225. {
  226. case FIELD_SHORT:
  227. {
  228. short *pValue = ( short* )( value );
  229. short nValue = pValue[iCount];
  230. Q_snprintf( szTempBuf, sizeof( szTempBuf ), "%d", nValue );
  231. Q_strncat( szBuf, szTempBuf, sizeof( szTempBuf ), COPY_ALL_CHARACTERS );
  232. break;
  233. }
  234. case FIELD_FLOAT:
  235. {
  236. float *pValue = ( float* )( value );
  237. float flValue = pValue[iCount];
  238. Q_snprintf( szTempBuf, sizeof( szTempBuf ), "%f", flValue );
  239. Q_strncat( szBuf, szTempBuf, sizeof( szTempBuf ), COPY_ALL_CHARACTERS );
  240. break;
  241. }
  242. case FIELD_BOOLEAN:
  243. {
  244. bool *pValue = ( bool* )( value );
  245. bool bValue = pValue[iCount];
  246. Q_snprintf( szTempBuf, sizeof( szTempBuf ), "%d", ( int )( bValue ) );
  247. Q_strncat( szBuf, szTempBuf, sizeof( szTempBuf ), COPY_ALL_CHARACTERS );
  248. break;
  249. }
  250. case FIELD_INTEGER:
  251. {
  252. int *pValue = ( int* )( value );
  253. int nValue = pValue[iCount];
  254. Q_snprintf( szTempBuf, sizeof( szTempBuf ), "%d", nValue );
  255. Q_strncat( szBuf, szTempBuf, sizeof( szTempBuf ), COPY_ALL_CHARACTERS );
  256. break;
  257. }
  258. case FIELD_STRING:
  259. {
  260. string_t *pValue = ( string_t* )( value );
  261. Q_snprintf( szTempBuf, sizeof( szTempBuf ), "%s", ( char* )STRING( *pValue ) );
  262. Q_strncat( szBuf, szTempBuf, sizeof( szTempBuf ), COPY_ALL_CHARACTERS );
  263. break;
  264. }
  265. case FIELD_VECTOR:
  266. {
  267. Vector *pValue = ( Vector* )( value );
  268. Vector vecValue = pValue[iCount];
  269. Q_snprintf( szTempBuf, sizeof( szTempBuf ), "(%f %f %f)", vecValue.x, vecValue.y, vecValue.z );
  270. Q_strncat( szBuf, szTempBuf, sizeof( szTempBuf ), COPY_ALL_CHARACTERS );
  271. break;
  272. }
  273. case FIELD_QUATERNION:
  274. {
  275. Quaternion *pValue = ( Quaternion* )( value );
  276. Quaternion q = pValue[iCount];
  277. Q_snprintf( szTempBuf, sizeof( szTempBuf ), "(%f %f %f %f)", q[0], q[1], q[2], q[3] );
  278. Q_strncat( szBuf, szTempBuf, sizeof( szTempBuf ), COPY_ALL_CHARACTERS );
  279. break;
  280. }
  281. case FIELD_CHARACTER:
  282. {
  283. char *pValue = ( char* )( value );
  284. char chValue = pValue[iCount];
  285. Q_snprintf( szTempBuf, sizeof( szTempBuf ), "%c", chValue );
  286. Q_strncat( szBuf, szTempBuf, sizeof( szTempBuf ), COPY_ALL_CHARACTERS );
  287. }
  288. case FIELD_COLOR32:
  289. {
  290. byte *pValue = ( byte* )( value );
  291. byte *pColor = &pValue[iCount*4];
  292. Q_snprintf( szTempBuf, sizeof( szTempBuf ), "(%d %d %d %d)", ( int )pColor[0], ( int )pColor[1], ( int )pColor[2], ( int )pColor[3] );
  293. Q_strncat( szBuf, szTempBuf, sizeof( szTempBuf ), COPY_ALL_CHARACTERS );
  294. }
  295. case FIELD_EMBEDDED:
  296. case FIELD_CUSTOM:
  297. default:
  298. {
  299. break;
  300. }
  301. }
  302. // Add space data.
  303. if ( ( iCount + 1 ) != count )
  304. {
  305. Q_strncpy( szTempBuf, " ", sizeof( szTempBuf ) );
  306. Q_strncat( szBuf, szTempBuf, sizeof( szTempBuf ), COPY_ALL_CHARACTERS );
  307. }
  308. else
  309. {
  310. Q_strncpy( szTempBuf, "\n", sizeof( szTempBuf ) );
  311. Q_strncat( szBuf, szTempBuf, sizeof( szTempBuf ), COPY_ALL_CHARACTERS );
  312. }
  313. }
  314. int nLength = strlen( szBuf ) + 1;
  315. filesystem->Write( szBuf, nLength, m_hLogFile );
  316. }
  317. //-------------------------------------
  318. bool CSave::IsAsync()
  319. {
  320. return m_bAsync;
  321. }
  322. //-------------------------------------
  323. int CSave::GetWritePos() const
  324. {
  325. return m_pData->GetCurPos();
  326. }
  327. //-------------------------------------
  328. void CSave::SetWritePos(int pos)
  329. {
  330. m_pData->Seek(pos);
  331. }
  332. //-------------------------------------
  333. void CSave::WriteShort( const short *value, int count )
  334. {
  335. BufferData( (const char *)value, sizeof(short) * count );
  336. }
  337. //-------------------------------------
  338. void CSave::WriteInt( const int *value, int count )
  339. {
  340. BufferData( (const char *)value, sizeof(int) * count );
  341. }
  342. //-------------------------------------
  343. void CSave::WriteBool( const bool *value, int count )
  344. {
  345. COMPILE_TIME_ASSERT( sizeof(bool) == sizeof(char) );
  346. BufferData( (const char *)value, sizeof(bool) * count );
  347. }
  348. //-------------------------------------
  349. void CSave::WriteFloat( const float *value, int count )
  350. {
  351. BufferData( (const char *)value, sizeof(float) * count );
  352. }
  353. //-------------------------------------
  354. void CSave::WriteData( const char *pdata , int size )
  355. {
  356. BufferData( pdata, size );
  357. }
  358. //-------------------------------------
  359. void CSave::WriteString( const char *pstring )
  360. {
  361. BufferData( pstring, strlen(pstring) + 1 );
  362. }
  363. //-------------------------------------
  364. void CSave::WriteString( const string_t *stringId, int count )
  365. {
  366. for ( int i = 0; i < count; i++ )
  367. {
  368. const char *pString = STRING(stringId[i]);
  369. BufferData( pString, strlen(pString)+1 );
  370. }
  371. }
  372. //-------------------------------------
  373. void CSave::WriteVector( const Vector &value )
  374. {
  375. BufferData( (const char *)&value, sizeof(Vector) );
  376. }
  377. //-------------------------------------
  378. void CSave::WriteVector( const Vector *value, int count )
  379. {
  380. BufferData( (const char *)value, sizeof(Vector) * count );
  381. }
  382. void CSave::WriteQuaternion( const Quaternion &value )
  383. {
  384. BufferData( (const char *)&value, sizeof(Quaternion) );
  385. }
  386. //-------------------------------------
  387. void CSave::WriteQuaternion( const Quaternion *value, int count )
  388. {
  389. BufferData( (const char *)value, sizeof(Quaternion) * count );
  390. }
  391. //-------------------------------------
  392. void CSave::WriteData( const char *pname, int size, const char *pdata )
  393. {
  394. BufferField( pname, size, pdata );
  395. }
  396. //-------------------------------------
  397. void CSave::WriteShort( const char *pname, const short *data, int count )
  398. {
  399. BufferField( pname, sizeof(short) * count, (const char *)data );
  400. }
  401. //-------------------------------------
  402. void CSave::WriteInt( const char *pname, const int *data, int count )
  403. {
  404. BufferField( pname, sizeof(int) * count, (const char *)data );
  405. }
  406. //-------------------------------------
  407. void CSave::WriteBool( const char *pname, const bool *data, int count )
  408. {
  409. COMPILE_TIME_ASSERT( sizeof(bool) == sizeof(char) );
  410. BufferField( pname, sizeof(bool) * count, (const char *)data );
  411. }
  412. //-------------------------------------
  413. void CSave::WriteFloat( const char *pname, const float *data, int count )
  414. {
  415. BufferField( pname, sizeof(float) * count, (const char *)data );
  416. }
  417. //-------------------------------------
  418. void CSave::WriteString( const char *pname, const char *pdata )
  419. {
  420. BufferField( pname, strlen(pdata) + 1, pdata );
  421. }
  422. //-------------------------------------
  423. void CSave::WriteString( const char *pname, const string_t *stringId, int count )
  424. {
  425. int i, size;
  426. size = 0;
  427. for ( i = 0; i < count; i++ )
  428. size += strlen( STRING( stringId[i] ) ) + 1;
  429. WriteHeader( pname, size );
  430. WriteString( stringId, count );
  431. }
  432. //-------------------------------------
  433. void CSave::WriteVector( const char *pname, const Vector &value )
  434. {
  435. WriteVector( pname, &value, 1 );
  436. }
  437. //-------------------------------------
  438. void CSave::WriteVector( const char *pname, const Vector *value, int count )
  439. {
  440. WriteHeader( pname, sizeof(Vector) * count );
  441. BufferData( (const char *)value, sizeof(Vector) * count );
  442. }
  443. void CSave::WriteQuaternion( const char *pname, const Quaternion &value )
  444. {
  445. WriteQuaternion( pname, &value, 1 );
  446. }
  447. //-------------------------------------
  448. void CSave::WriteQuaternion( const char *pname, const Quaternion *value, int count )
  449. {
  450. WriteHeader( pname, sizeof(Quaternion) * count );
  451. BufferData( (const char *)value, sizeof(Quaternion) * count );
  452. }
  453. //-------------------------------------
  454. void CSave::WriteVMatrix( const VMatrix *value, int count )
  455. {
  456. BufferData( (const char *)value, sizeof(VMatrix) * count );
  457. }
  458. //-------------------------------------
  459. void CSave::WriteVMatrix( const char *pname, const VMatrix *value, int count )
  460. {
  461. WriteHeader( pname, sizeof(VMatrix) * count );
  462. BufferData( (const char *)value, sizeof(VMatrix) * count );
  463. }
  464. //-------------------------------------
  465. void CSave::WriteVMatrixWorldspace( const VMatrix *value, int count )
  466. {
  467. for ( int i = 0; i < count; i++ )
  468. {
  469. VMatrix tmp;
  470. VMatrixOffset( tmp, value[i], -m_pGameInfo->GetLandmark() );
  471. BufferData( (const char *)&tmp, sizeof(VMatrix) );
  472. }
  473. }
  474. //-------------------------------------
  475. void CSave::WriteVMatrixWorldspace( const char *pname, const VMatrix *value, int count )
  476. {
  477. WriteHeader( pname, sizeof(VMatrix) * count );
  478. WriteVMatrixWorldspace( value, count );
  479. }
  480. void CSave::WriteMatrix3x4Worldspace( const matrix3x4_t *value, int count )
  481. {
  482. Vector offset = -m_pGameInfo->GetLandmark();
  483. for ( int i = 0; i < count; i++ )
  484. {
  485. matrix3x4_t tmp;
  486. Matrix3x4Offset( tmp, value[i], offset );
  487. BufferData( (const char *)value, sizeof(matrix3x4_t) );
  488. }
  489. }
  490. //-------------------------------------
  491. void CSave::WriteMatrix3x4Worldspace( const char *pname, const matrix3x4_t *value, int count )
  492. {
  493. WriteHeader( pname, sizeof(matrix3x4_t) * count );
  494. WriteMatrix3x4Worldspace( value, count );
  495. }
  496. void CSave::WriteInterval( const char *pname, const interval_t *value, int count )
  497. {
  498. WriteHeader( pname, sizeof( interval_t ) * count );
  499. WriteInterval( value, count );
  500. }
  501. void CSave::WriteInterval( const interval_t *value, int count )
  502. {
  503. BufferData( (const char *)value, count * sizeof( interval_t ) );
  504. }
  505. //-------------------------------------
  506. bool CSave::ShouldSaveField( const void *pData, typedescription_t *pField )
  507. {
  508. if ( !(pField->flags & FTYPEDESC_SAVE) || pField->fieldType == FIELD_VOID )
  509. return false;
  510. switch ( pField->fieldType )
  511. {
  512. case FIELD_EMBEDDED:
  513. {
  514. if ( pField->flags & FTYPEDESC_PTR )
  515. {
  516. AssertMsg( pField->fieldSize == 1, "Arrays of embedded pointer types presently unsupported by save/restore" );
  517. if ( pField->fieldSize != 1 )
  518. return false;
  519. }
  520. AssertMsg( pField->td != NULL, "Embedded type appears to have not had type description implemented" );
  521. if ( pField->td == NULL )
  522. return false;
  523. if ( (pField->flags & FTYPEDESC_PTR) && !*((void **)pData) )
  524. return false;
  525. // @TODO: need real logic for handling embedded types with base classes
  526. if ( pField->td->baseMap )
  527. {
  528. return true;
  529. }
  530. int nFieldCount = pField->fieldSize;
  531. char *pTestData = (char *)( ( !(pField->flags & FTYPEDESC_PTR) ) ? pData : *((void **)pData) );
  532. while ( --nFieldCount >= 0 )
  533. {
  534. typedescription_t *pTestField = pField->td->dataDesc;
  535. typedescription_t *pLimit = pField->td->dataDesc + pField->td->dataNumFields;
  536. for ( ; pTestField < pLimit; ++pTestField )
  537. {
  538. if ( ShouldSaveField( pTestData + pTestField->fieldOffset[ TD_OFFSET_NORMAL ], pTestField ) )
  539. return true;
  540. }
  541. pTestData += pField->fieldSizeInBytes;
  542. }
  543. return false;
  544. }
  545. case FIELD_CUSTOM:
  546. {
  547. // ask the data if it's empty
  548. SaveRestoreFieldInfo_t fieldInfo =
  549. {
  550. const_cast<void *>(pData),
  551. ((char *)pData) - pField->fieldOffset[ TD_OFFSET_NORMAL ],
  552. pField
  553. };
  554. if ( pField->pSaveRestoreOps->IsEmpty( fieldInfo ) )
  555. return false;
  556. }
  557. return true;
  558. case FIELD_EHANDLE:
  559. {
  560. if ( (pField->fieldSizeInBytes != pField->fieldSize * gSizes[pField->fieldType]) )
  561. {
  562. Warning("WARNING! Field %s is using the wrong FIELD_ type!\nFix this or you'll see a crash.\n", pField->fieldName );
  563. Assert( 0 );
  564. }
  565. int *pEHandle = (int *)pData;
  566. for ( int i = 0; i < pField->fieldSize; ++i, ++pEHandle )
  567. {
  568. if ( (*pEHandle) != 0xFFFFFFFF )
  569. return true;
  570. }
  571. }
  572. return false;
  573. default:
  574. {
  575. if ( (pField->fieldSizeInBytes != pField->fieldSize * gSizes[pField->fieldType]) )
  576. {
  577. Warning("WARNING! Field %s is using the wrong FIELD_ type!\nFix this or you'll see a crash.\n", pField->fieldName );
  578. Assert( 0 );
  579. }
  580. // old byte-by-byte null check
  581. if ( DataEmpty( (const char *)pData, pField->fieldSize * gSizes[pField->fieldType] ) )
  582. return false;
  583. }
  584. return true;
  585. }
  586. }
  587. //-------------------------------------
  588. // Purpose: Writes all the fields that are client neutral. In the event of
  589. // a librarization of save/restore, these would reside in the library
  590. //
  591. bool CSave::WriteBasicField( const char *pname, void *pData, datamap_t *pRootMap, typedescription_t *pField )
  592. {
  593. switch( pField->fieldType )
  594. {
  595. case FIELD_FLOAT:
  596. WriteFloat( pField->fieldName, (float *)pData, pField->fieldSize );
  597. break;
  598. case FIELD_STRING:
  599. WriteString( pField->fieldName, (string_t *)pData, pField->fieldSize );
  600. break;
  601. case FIELD_VECTOR:
  602. WriteVector( pField->fieldName, (Vector *)pData, pField->fieldSize );
  603. break;
  604. case FIELD_QUATERNION:
  605. WriteQuaternion( pField->fieldName, (Quaternion *)pData, pField->fieldSize );
  606. break;
  607. case FIELD_INTEGER:
  608. WriteInt( pField->fieldName, (int *)pData, pField->fieldSize );
  609. break;
  610. case FIELD_BOOLEAN:
  611. WriteBool( pField->fieldName, (bool *)pData, pField->fieldSize );
  612. break;
  613. case FIELD_SHORT:
  614. WriteData( pField->fieldName, 2 * pField->fieldSize, ((char *)pData) );
  615. break;
  616. case FIELD_CHARACTER:
  617. WriteData( pField->fieldName, pField->fieldSize, ((char *)pData) );
  618. break;
  619. case FIELD_COLOR32:
  620. WriteData( pField->fieldName, 4*pField->fieldSize, (char *)pData );
  621. break;
  622. case FIELD_EMBEDDED:
  623. {
  624. AssertMsg( ( (pField->flags & FTYPEDESC_PTR) == 0 ) || (pField->fieldSize == 1), "Arrays of embedded pointer types presently unsupported by save/restore" );
  625. Assert( !(pField->flags & FTYPEDESC_PTR) || *((void **)pData) );
  626. int nFieldCount = pField->fieldSize;
  627. char *pFieldData = (char *)( ( !(pField->flags & FTYPEDESC_PTR) ) ? pData : *((void **)pData) );
  628. StartBlock( pField->fieldName );
  629. while ( --nFieldCount >= 0 )
  630. {
  631. WriteAll( pFieldData, pField->td );
  632. pFieldData += pField->fieldSizeInBytes;
  633. }
  634. EndBlock();
  635. break;
  636. }
  637. case FIELD_CUSTOM:
  638. {
  639. // Note it is up to the custom type implementor to handle arrays
  640. StartBlock( pField->fieldName );
  641. SaveRestoreFieldInfo_t fieldInfo =
  642. {
  643. pData,
  644. ((char *)pData) - pField->fieldOffset[ TD_OFFSET_NORMAL ],
  645. pField
  646. };
  647. pField->pSaveRestoreOps->Save( fieldInfo, this );
  648. EndBlock();
  649. break;
  650. }
  651. default:
  652. Warning( "Bad field type\n" );
  653. Assert(0);
  654. return false;
  655. }
  656. return true;
  657. }
  658. //-------------------------------------
  659. bool CSave::WriteField( const char *pname, void *pData, datamap_t *pRootMap, typedescription_t *pField )
  660. {
  661. #ifdef _DEBUG
  662. Log( pname, (fieldtype_t)pField->fieldType, pData, pField->fieldSize );
  663. #endif
  664. if ( pField->fieldType <= FIELD_CUSTOM )
  665. {
  666. return WriteBasicField( pname, pData, pRootMap, pField );
  667. }
  668. return WriteGameField( pname, pData, pRootMap, pField );
  669. }
  670. //-------------------------------------
  671. int CSave::WriteFields( const char *pname, const void *pBaseData, datamap_t *pRootMap, typedescription_t *pFields, int fieldCount )
  672. {
  673. typedescription_t *pTest;
  674. int iHeaderPos = m_pData->GetCurPos();
  675. int count = -1;
  676. WriteInt( pname, &count, 1 );
  677. count = 0;
  678. #ifdef _X360
  679. __dcbt( 0, pBaseData );
  680. __dcbt( 128, pBaseData );
  681. __dcbt( 256, pBaseData );
  682. __dcbt( 512, pBaseData );
  683. void *pDest = m_pData->AccessCurPos();
  684. __dcbt( 0, pDest );
  685. __dcbt( 128, pDest );
  686. __dcbt( 256, pDest );
  687. __dcbt( 512, pDest );
  688. #endif
  689. for ( int i = 0; i < fieldCount; i++ )
  690. {
  691. pTest = &pFields[ i ];
  692. void *pOutputData = ( (char *)pBaseData + pTest->fieldOffset[ TD_OFFSET_NORMAL ] );
  693. if ( !ShouldSaveField( pOutputData, pTest ) )
  694. continue;
  695. if ( !WriteField( pname, pOutputData, pRootMap, pTest ) )
  696. break;
  697. count++;
  698. }
  699. int iCurPos = m_pData->GetCurPos();
  700. int iRewind = iCurPos - iHeaderPos;
  701. m_pData->Rewind( iRewind );
  702. WriteInt( pname, &count, 1 );
  703. iCurPos = m_pData->GetCurPos();
  704. m_pData->MoveCurPos( iRewind - ( iCurPos - iHeaderPos ) );
  705. return 1;
  706. }
  707. //-------------------------------------
  708. // Purpose: Recursively saves all the classes in an object, in reverse order (top down)
  709. // Output : int 0 on failure, 1 on success
  710. int CSave::DoWriteAll( const void *pLeafObject, datamap_t *pLeafMap, datamap_t *pCurMap )
  711. {
  712. // save base classes first
  713. if ( pCurMap->baseMap )
  714. {
  715. int status = DoWriteAll( pLeafObject, pLeafMap, pCurMap->baseMap );
  716. if ( !status )
  717. return status;
  718. }
  719. return WriteFields( pCurMap->dataClassName, pLeafObject, pLeafMap, pCurMap->dataDesc, pCurMap->dataNumFields );
  720. }
  721. //-------------------------------------
  722. void CSave::StartBlock( const char *pszBlockName )
  723. {
  724. WriteHeader( pszBlockName, 0 ); // placeholder
  725. m_BlockStartStack.AddToTail( GetWritePos() );
  726. }
  727. //-------------------------------------
  728. void CSave::StartBlock()
  729. {
  730. StartBlock( "" );
  731. }
  732. //-------------------------------------
  733. void CSave::EndBlock()
  734. {
  735. int endPos = GetWritePos();
  736. int startPos = m_BlockStartStack[ m_BlockStartStack.Count() - 1 ];
  737. short sizeBlock = endPos - startPos;
  738. m_BlockStartStack.Remove( m_BlockStartStack.Count() - 1 );
  739. // Move to the the location where the size of the block was written & rewrite the size
  740. SetWritePos( startPos - sizeof(SaveRestoreRecordHeader_t) );
  741. BufferData( (const char *)&sizeBlock, sizeof(short) );
  742. SetWritePos( endPos );
  743. }
  744. //-------------------------------------
  745. void CSave::BufferString( char *pdata, int len )
  746. {
  747. char c = 0;
  748. BufferData( pdata, len ); // Write the string
  749. BufferData( &c, 1 ); // Write a null terminator
  750. }
  751. //-------------------------------------
  752. void CSave::BufferField( const char *pname, int size, const char *pdata )
  753. {
  754. WriteHeader( pname, size );
  755. BufferData( pdata, size );
  756. }
  757. //-------------------------------------
  758. void CSave::WriteHeader( const char *pname, int size )
  759. {
  760. short shortSize = size;
  761. short hashvalue = m_pData->FindCreateSymbol( pname );
  762. if ( size > SHRT_MAX || size < 0 )
  763. {
  764. Warning( "CSave::WriteHeader() size parameter exceeds 'short'!\n" );
  765. Assert(0);
  766. }
  767. BufferData( (const char *)&shortSize, sizeof(short) );
  768. BufferData( (const char *)&hashvalue, sizeof(short) );
  769. }
  770. //-------------------------------------
  771. void CSave::BufferData( const char *pdata, int size )
  772. {
  773. if ( !m_pData )
  774. return;
  775. if ( !m_pData->Write( pdata, size ) )
  776. {
  777. Warning( "Save/Restore overflow!\n" );
  778. Assert(0);
  779. }
  780. }
  781. //---------------------------------------------------------
  782. //
  783. // Game centric save methods.
  784. //
  785. int CSave::EntityIndex( const edict_t *pentLookup )
  786. {
  787. #if !defined( CLIENT_DLL )
  788. if ( pentLookup == NULL )
  789. return -1;
  790. return EntityIndex( CBaseEntity::Instance(pentLookup) );
  791. #else
  792. Assert( !"CSave::EntityIndex( edict_t * ) not valid on client!" );
  793. return -1;
  794. #endif
  795. }
  796. //-------------------------------------
  797. int CSave::EntityIndex( const CBaseEntity *pEntity )
  798. {
  799. return m_pGameInfo->GetEntityIndex( pEntity );
  800. }
  801. //-------------------------------------
  802. int CSave::EntityFlagsSet( int entityIndex, int flags )
  803. {
  804. if ( !m_pGameInfo || entityIndex < 0 )
  805. return 0;
  806. if ( entityIndex > m_pGameInfo->NumEntities() )
  807. return 0;
  808. m_pGameInfo->GetEntityInfo( entityIndex )->flags |= flags;
  809. return m_pGameInfo->GetEntityInfo( entityIndex )->flags;
  810. }
  811. //-------------------------------------
  812. void CSave::WriteTime( const char *pname, const float *data, int count )
  813. {
  814. int i;
  815. float tmp;
  816. WriteHeader( pname, sizeof(float) * count );
  817. for ( i = 0; i < count; i++ )
  818. {
  819. // Always encode time as a delta from the current time so it can be re-based if loaded in a new level
  820. // Times of 0 are never written to the file, so they will be restored as 0, not a relative time
  821. Assert( data[i] != ZERO_TIME );
  822. if ( data[i] == 0.0 )
  823. {
  824. tmp = ZERO_TIME;
  825. }
  826. else if ( data[i] == INVALID_TIME || data[i] == FLT_MAX )
  827. {
  828. tmp = data[i];
  829. }
  830. else
  831. {
  832. tmp = data[i] - m_pGameInfo->GetBaseTime();
  833. if ( fabsf( tmp ) < 0.001 ) // never allow a time to become zero due to rebasing
  834. tmp = 0.001;
  835. }
  836. WriteData( (const char *)&tmp, sizeof(float) );
  837. }
  838. }
  839. //-------------------------------------
  840. void CSave::WriteTime( const float *data, int count )
  841. {
  842. int i;
  843. float tmp;
  844. for ( i = 0; i < count; i++ )
  845. {
  846. // Always encode time as a delta from the current time so it can be re-based if loaded in a new level
  847. // Times of 0 are never written to the file, so they will be restored as 0, not a relative time
  848. if ( data[i] == 0.0 )
  849. {
  850. tmp = ZERO_TIME;
  851. }
  852. else if ( data[i] == INVALID_TIME || data[i] == FLT_MAX )
  853. {
  854. tmp = data[i];
  855. }
  856. else
  857. {
  858. tmp = data[i] - m_pGameInfo->GetBaseTime();
  859. if ( fabsf( tmp ) < 0.001 ) // never allow a time to become zero due to rebasing
  860. tmp = 0.001;
  861. }
  862. WriteData( (const char *)&tmp, sizeof(float) );
  863. }
  864. }
  865. void CSave::WriteTick( const char *pname, const int *data, int count )
  866. {
  867. WriteHeader( pname, sizeof(int) * count );
  868. WriteTick( data, count );
  869. }
  870. //-------------------------------------
  871. void CSave::WriteTick( const int *data, int count )
  872. {
  873. int i;
  874. int tmp;
  875. int baseTick = TIME_TO_TICKS( m_pGameInfo->GetBaseTime() );
  876. for ( i = 0; i < count; i++ )
  877. {
  878. // Always encode time as a delta from the current time so it can be re-based if loaded in a new level
  879. // Times of 0 are never written to the file, so they will be restored as 0, not a relative time
  880. tmp = data[ i ];
  881. if ( data[ i ] == TICK_NEVER_THINK )
  882. {
  883. tmp = TICK_NEVER_THINK_ENCODE;
  884. }
  885. else
  886. {
  887. // Rebase it...
  888. tmp -= baseTick;
  889. }
  890. WriteData( (const char *)&tmp, sizeof(int) );
  891. }
  892. }
  893. //-------------------------------------
  894. void CSave::WritePositionVector( const char *pname, const Vector &value )
  895. {
  896. Vector tmp = value;
  897. if ( tmp != vec3_invalid )
  898. tmp -= m_pGameInfo->GetLandmark();
  899. WriteVector( pname, tmp );
  900. }
  901. //-------------------------------------
  902. void CSave::WritePositionVector( const Vector &value )
  903. {
  904. Vector tmp = value;
  905. if ( tmp != vec3_invalid )
  906. tmp -= m_pGameInfo->GetLandmark();
  907. WriteVector( tmp );
  908. }
  909. //-------------------------------------
  910. void CSave::WritePositionVector( const char *pname, const Vector *value, int count )
  911. {
  912. WriteHeader( pname, sizeof(Vector) * count );
  913. WritePositionVector( value, count );
  914. }
  915. //-------------------------------------
  916. void CSave::WritePositionVector( const Vector *value, int count )
  917. {
  918. for ( int i = 0; i < count; i++ )
  919. {
  920. Vector tmp = value[i];
  921. if ( tmp != vec3_invalid )
  922. tmp -= m_pGameInfo->GetLandmark();
  923. WriteData( (const char *)&tmp.x, sizeof(Vector) );
  924. }
  925. }
  926. //-------------------------------------
  927. void CSave::WriteFunction( datamap_t *pRootMap, const char *pname, inputfunc_t **data, int count )
  928. {
  929. AssertMsg( count == 1, "Arrays of functions not presently supported" );
  930. const char *functionName = UTIL_FunctionToName( pRootMap, *data );
  931. if ( !functionName )
  932. {
  933. Warning( "Invalid function pointer in entity!\n" );
  934. Assert(0);
  935. functionName = "BADFUNCTIONPOINTER";
  936. }
  937. BufferField( pname, strlen(functionName) + 1, functionName );
  938. }
  939. //-------------------------------------
  940. void CSave::WriteEntityPtr( const char *pname, CBaseEntity **ppEntity, int count )
  941. {
  942. AssertMsg( count <= MAX_ENTITYARRAY, "Array of entities or ehandles exceeds limit supported by save/restore" );
  943. int entityArray[MAX_ENTITYARRAY];
  944. for ( int i = 0; i < count && i < MAX_ENTITYARRAY; i++ )
  945. {
  946. entityArray[i] = EntityIndex( ppEntity[i] );
  947. }
  948. WriteInt( pname, entityArray, count );
  949. }
  950. //-------------------------------------
  951. void CSave::WriteEntityPtr( CBaseEntity **ppEntity, int count )
  952. {
  953. AssertMsg( count <= MAX_ENTITYARRAY, "Array of entities or ehandles exceeds limit supported by save/restore" );
  954. int entityArray[MAX_ENTITYARRAY];
  955. for ( int i = 0; i < count && i < MAX_ENTITYARRAY; i++ )
  956. {
  957. entityArray[i] = EntityIndex( ppEntity[i] );
  958. }
  959. WriteInt( entityArray, count );
  960. }
  961. //-------------------------------------
  962. void CSave::WriteEdictPtr( const char *pname, edict_t **ppEdict, int count )
  963. {
  964. AssertMsg( count <= MAX_ENTITYARRAY, "Array of entities or ehandles exceeds limit supported by save/restore" );
  965. int entityArray[MAX_ENTITYARRAY];
  966. for ( int i = 0; i < count && i < MAX_ENTITYARRAY; i++ )
  967. {
  968. entityArray[i] = EntityIndex( ppEdict[i] );
  969. }
  970. WriteInt( pname, entityArray, count );
  971. }
  972. //-------------------------------------
  973. void CSave::WriteEdictPtr( edict_t **ppEdict, int count )
  974. {
  975. AssertMsg( count <= MAX_ENTITYARRAY, "Array of entities or ehandles exceeds limit supported by save/restore" );
  976. int entityArray[MAX_ENTITYARRAY];
  977. for ( int i = 0; i < count && i < MAX_ENTITYARRAY; i++ )
  978. {
  979. entityArray[i] = EntityIndex( ppEdict[i] );
  980. }
  981. WriteInt( entityArray, count );
  982. }
  983. //-------------------------------------
  984. void CSave::WriteEHandle( const char *pname, const EHANDLE *pEHandle, int count )
  985. {
  986. AssertMsg( count <= MAX_ENTITYARRAY, "Array of entities or ehandles exceeds limit supported by save/restore" );
  987. int entityArray[MAX_ENTITYARRAY];
  988. for ( int i = 0; i < count && i < MAX_ENTITYARRAY; i++ )
  989. {
  990. entityArray[i] = EntityIndex( (CBaseEntity *)(const_cast<EHANDLE *>(pEHandle)[i]) );
  991. }
  992. WriteInt( pname, entityArray, count );
  993. }
  994. //-------------------------------------
  995. void CSave::WriteEHandle( const EHANDLE *pEHandle, int count )
  996. {
  997. AssertMsg( count <= MAX_ENTITYARRAY, "Array of entities or ehandles exceeds limit supported by save/restore" );
  998. int entityArray[MAX_ENTITYARRAY];
  999. for ( int i = 0; i < count && i < MAX_ENTITYARRAY; i++ )
  1000. {
  1001. entityArray[i] = EntityIndex( (CBaseEntity *)(const_cast<EHANDLE *>(pEHandle)[i]) );
  1002. }
  1003. WriteInt( entityArray, count );
  1004. }
  1005. //-------------------------------------
  1006. // Purpose: Writes all the fields that are not client neutral. In the event of
  1007. // a librarization of save/restore, these would not reside in the library
  1008. bool CSave::WriteGameField( const char *pname, void *pData, datamap_t *pRootMap, typedescription_t *pField )
  1009. {
  1010. switch( pField->fieldType )
  1011. {
  1012. case FIELD_CLASSPTR:
  1013. WriteEntityPtr( pField->fieldName, (CBaseEntity **)pData, pField->fieldSize );
  1014. break;
  1015. case FIELD_EDICT:
  1016. WriteEdictPtr( pField->fieldName, (edict_t **)pData, pField->fieldSize );
  1017. break;
  1018. case FIELD_EHANDLE:
  1019. WriteEHandle( pField->fieldName, (EHANDLE *)pData, pField->fieldSize );
  1020. break;
  1021. case FIELD_POSITION_VECTOR:
  1022. WritePositionVector( pField->fieldName, (Vector *)pData, pField->fieldSize );
  1023. break;
  1024. case FIELD_TIME:
  1025. WriteTime( pField->fieldName, (float *)pData, pField->fieldSize );
  1026. break;
  1027. case FIELD_TICK:
  1028. WriteTick( pField->fieldName, (int *)pData, pField->fieldSize );
  1029. break;
  1030. case FIELD_MODELINDEX:
  1031. {
  1032. int nModelIndex = *(int*)pData;
  1033. string_t strModelName = NULL_STRING;
  1034. const model_t *pModel = modelinfo->GetModel( nModelIndex );
  1035. if ( pModel )
  1036. {
  1037. strModelName = AllocPooledString( modelinfo->GetModelName( pModel ) );
  1038. }
  1039. WriteString( pField->fieldName, (string_t *)&strModelName, pField->fieldSize );
  1040. }
  1041. break;
  1042. case FIELD_MATERIALINDEX:
  1043. {
  1044. int nMateralIndex = *(int*)pData;
  1045. string_t strMaterialName = NULL_STRING;
  1046. const char *pMaterialName = GetMaterialNameFromIndex( nMateralIndex );
  1047. if ( pMaterialName )
  1048. {
  1049. strMaterialName = MAKE_STRING( pMaterialName );
  1050. }
  1051. WriteString( pField->fieldName, (string_t *)&strMaterialName, pField->fieldSize );
  1052. }
  1053. break;
  1054. case FIELD_MODELNAME:
  1055. case FIELD_SOUNDNAME:
  1056. WriteString( pField->fieldName, (string_t *)pData, pField->fieldSize );
  1057. break;
  1058. // For now, just write the address out, we're not going to change memory while doing this yet!
  1059. case FIELD_FUNCTION:
  1060. WriteFunction( pRootMap, pField->fieldName, (inputfunc_t **)(char *)pData, pField->fieldSize );
  1061. break;
  1062. case FIELD_VMATRIX:
  1063. WriteVMatrix( pField->fieldName, (VMatrix *)pData, pField->fieldSize );
  1064. break;
  1065. case FIELD_VMATRIX_WORLDSPACE:
  1066. WriteVMatrixWorldspace( pField->fieldName, (VMatrix *)pData, pField->fieldSize );
  1067. break;
  1068. case FIELD_MATRIX3X4_WORLDSPACE:
  1069. WriteMatrix3x4Worldspace( pField->fieldName, (const matrix3x4_t *)pData, pField->fieldSize );
  1070. break;
  1071. case FIELD_INTERVAL:
  1072. WriteInterval( pField->fieldName, (interval_t *)pData, pField->fieldSize );
  1073. break;
  1074. default:
  1075. Warning( "Bad field type\n" );
  1076. Assert(0);
  1077. return false;
  1078. }
  1079. return true;
  1080. }
  1081. //-----------------------------------------------------------------------------
  1082. //
  1083. // CRestore
  1084. //
  1085. //-----------------------------------------------------------------------------
  1086. CRestore::CRestore( CSaveRestoreData *pdata )
  1087. : m_pData( pdata ),
  1088. m_pGameInfo( pdata ),
  1089. m_global( 0 ),
  1090. m_precache( true )
  1091. {
  1092. m_BlockEndStack.EnsureCapacity( 32 );
  1093. }
  1094. //-------------------------------------
  1095. int CRestore::GetReadPos() const
  1096. {
  1097. return m_pData->GetCurPos();
  1098. }
  1099. //-------------------------------------
  1100. void CRestore::SetReadPos( int pos )
  1101. {
  1102. m_pData->Seek(pos);
  1103. }
  1104. //-------------------------------------
  1105. const char *CRestore::StringFromHeaderSymbol( int symbol )
  1106. {
  1107. const char *pszResult = m_pData->StringFromSymbol( symbol );
  1108. return ( pszResult ) ? pszResult : "";
  1109. }
  1110. //-------------------------------------
  1111. // Purpose: Reads all the fields that are client neutral. In the event of
  1112. // a librarization of save/restore, these would reside in the library
  1113. void CRestore::ReadBasicField( const SaveRestoreRecordHeader_t &header, void *pDest, datamap_t *pRootMap, typedescription_t *pField )
  1114. {
  1115. switch( pField->fieldType )
  1116. {
  1117. case FIELD_FLOAT:
  1118. {
  1119. ReadFloat( (float *)pDest, pField->fieldSize, header.size );
  1120. break;
  1121. }
  1122. case FIELD_STRING:
  1123. {
  1124. ReadString( (string_t *)pDest, pField->fieldSize, header.size );
  1125. break;
  1126. }
  1127. case FIELD_VECTOR:
  1128. {
  1129. ReadVector( (Vector *)pDest, pField->fieldSize, header.size );
  1130. break;
  1131. }
  1132. case FIELD_QUATERNION:
  1133. {
  1134. ReadQuaternion( (Quaternion *)pDest, pField->fieldSize, header.size );
  1135. break;
  1136. }
  1137. case FIELD_INTEGER:
  1138. {
  1139. ReadInt( (int *)pDest, pField->fieldSize, header.size );
  1140. break;
  1141. }
  1142. case FIELD_BOOLEAN:
  1143. {
  1144. ReadBool( (bool *)pDest, pField->fieldSize, header.size );
  1145. break;
  1146. }
  1147. case FIELD_SHORT:
  1148. {
  1149. ReadShort( (short *)pDest, pField->fieldSize, header.size );
  1150. break;
  1151. }
  1152. case FIELD_CHARACTER:
  1153. {
  1154. ReadData( (char *)pDest, pField->fieldSize, header.size );
  1155. break;
  1156. }
  1157. case FIELD_COLOR32:
  1158. {
  1159. COMPILE_TIME_ASSERT( sizeof(color32) == sizeof(int) );
  1160. ReadInt( (int *)pDest, pField->fieldSize, header.size );
  1161. break;
  1162. }
  1163. case FIELD_EMBEDDED:
  1164. {
  1165. AssertMsg( (( pField->flags & FTYPEDESC_PTR ) == 0) || (pField->fieldSize == 1), "Arrays of embedded pointer types presently unsupported by save/restore" );
  1166. #ifdef DBGFLAG_ASSERT
  1167. int startPos = GetReadPos();
  1168. #endif
  1169. if ( !(pField->flags & FTYPEDESC_PTR) || *((void **)pDest) )
  1170. {
  1171. int nFieldCount = pField->fieldSize;
  1172. char *pFieldData = (char *)( ( !(pField->flags & FTYPEDESC_PTR) ) ? pDest : *((void **)pDest) );
  1173. while ( --nFieldCount >= 0 )
  1174. {
  1175. // No corresponding "block" (see write) as it was used as the header of the field
  1176. ReadAll( pFieldData, pField->td );
  1177. pFieldData += pField->fieldSizeInBytes;
  1178. }
  1179. Assert( GetReadPos() - startPos == header.size );
  1180. }
  1181. else
  1182. {
  1183. SetReadPos( GetReadPos() + header.size );
  1184. Warning( "Attempted to restore FIELD_EMBEDDEDBYREF %s but there is no destination memory\n", pField->fieldName );
  1185. }
  1186. break;
  1187. }
  1188. case FIELD_CUSTOM:
  1189. {
  1190. // No corresponding "block" (see write) as it was used as the header of the field
  1191. int posNextField = GetReadPos() + header.size;
  1192. SaveRestoreFieldInfo_t fieldInfo =
  1193. {
  1194. pDest,
  1195. ((char *)pDest) - pField->fieldOffset[ TD_OFFSET_NORMAL ],
  1196. pField
  1197. };
  1198. pField->pSaveRestoreOps->Restore( fieldInfo, this );
  1199. Assert( posNextField >= GetReadPos() );
  1200. SetReadPos( posNextField );
  1201. break;
  1202. }
  1203. default:
  1204. Warning( "Bad field type\n" );
  1205. Assert(0);
  1206. }
  1207. }
  1208. //-------------------------------------
  1209. void CRestore::ReadField( const SaveRestoreRecordHeader_t &header, void *pDest, datamap_t *pRootMap, typedescription_t *pField )
  1210. {
  1211. if ( pField->fieldType <= FIELD_CUSTOM )
  1212. ReadBasicField( header, pDest, pRootMap, pField );
  1213. else
  1214. ReadGameField( header, pDest, pRootMap, pField );
  1215. }
  1216. //-------------------------------------
  1217. bool CRestore::ShouldReadField( typedescription_t *pField )
  1218. {
  1219. if ( (pField->flags & FTYPEDESC_SAVE) == 0 )
  1220. return false;
  1221. if ( m_global && (pField->flags & FTYPEDESC_GLOBAL) )
  1222. return false;
  1223. return true;
  1224. }
  1225. //-------------------------------------
  1226. typedescription_t *CRestore::FindField( const char *pszFieldName, typedescription_t *pFields, int fieldCount, int *pCookie )
  1227. {
  1228. int &fieldNumber = *pCookie;
  1229. if ( pszFieldName )
  1230. {
  1231. typedescription_t *pTest;
  1232. for ( int i = 0; i < fieldCount; i++ )
  1233. {
  1234. pTest = &pFields[fieldNumber];
  1235. ++fieldNumber;
  1236. if ( fieldNumber == fieldCount )
  1237. fieldNumber = 0;
  1238. if ( stricmp( pTest->fieldName, pszFieldName ) == 0 )
  1239. return pTest;
  1240. }
  1241. }
  1242. fieldNumber = 0;
  1243. return NULL;
  1244. }
  1245. //-------------------------------------
  1246. bool CRestore::ShouldEmptyField( typedescription_t *pField )
  1247. {
  1248. // don't clear out fields that don't get saved, or that are handled specially
  1249. if ( !( pField->flags & FTYPEDESC_SAVE ) )
  1250. return false;
  1251. // Don't clear global fields
  1252. if ( m_global && (pField->flags & FTYPEDESC_GLOBAL) )
  1253. return false;
  1254. return true;
  1255. }
  1256. //-------------------------------------
  1257. void CRestore::EmptyFields( void *pBaseData, typedescription_t *pFields, int fieldCount )
  1258. {
  1259. int i;
  1260. for ( i = 0; i < fieldCount; i++ )
  1261. {
  1262. typedescription_t *pField = &pFields[i];
  1263. if ( !ShouldEmptyField( pField ) )
  1264. continue;
  1265. void *pFieldData = (char *)pBaseData + pField->fieldOffset[ TD_OFFSET_NORMAL ];
  1266. switch( pField->fieldType )
  1267. {
  1268. case FIELD_CUSTOM:
  1269. {
  1270. SaveRestoreFieldInfo_t fieldInfo =
  1271. {
  1272. pFieldData,
  1273. pBaseData,
  1274. pField
  1275. };
  1276. pField->pSaveRestoreOps->MakeEmpty( fieldInfo );
  1277. }
  1278. break;
  1279. case FIELD_EMBEDDED:
  1280. {
  1281. if ( (pField->flags & FTYPEDESC_PTR) && !*((void **)pFieldData) )
  1282. break;
  1283. int nFieldCount = pField->fieldSize;
  1284. char *pFieldMemory = (char *)( ( !(pField->flags & FTYPEDESC_PTR) ) ? pFieldData : *((void **)pFieldData) );
  1285. while ( --nFieldCount >= 0 )
  1286. {
  1287. EmptyFields( pFieldMemory, pField->td->dataDesc, pField->td->dataNumFields );
  1288. pFieldMemory += pField->fieldSizeInBytes;
  1289. }
  1290. }
  1291. break;
  1292. default:
  1293. // NOTE: If you hit this assertion, you've got a bug where you're using
  1294. // the wrong field type for your field
  1295. if ( pField->fieldSizeInBytes != pField->fieldSize * gSizes[pField->fieldType] )
  1296. {
  1297. Warning("WARNING! Field %s is using the wrong FIELD_ type!\nFix this or you'll see a crash.\n", pField->fieldName );
  1298. Assert( 0 );
  1299. }
  1300. memset( pFieldData, (pField->fieldType != FIELD_EHANDLE) ? 0 : 0xFF, pField->fieldSize * gSizes[pField->fieldType] );
  1301. break;
  1302. }
  1303. }
  1304. }
  1305. //-------------------------------------
  1306. void CRestore::StartBlock( SaveRestoreRecordHeader_t *pHeader )
  1307. {
  1308. ReadHeader( pHeader );
  1309. m_BlockEndStack.AddToTail( GetReadPos() + pHeader->size );
  1310. }
  1311. //-------------------------------------
  1312. void CRestore::StartBlock( char szBlockName[] )
  1313. {
  1314. SaveRestoreRecordHeader_t header;
  1315. StartBlock( &header );
  1316. Q_strncpy( szBlockName, StringFromHeaderSymbol( header.symbol ), SIZE_BLOCK_NAME_BUF );
  1317. }
  1318. //-------------------------------------
  1319. void CRestore::StartBlock()
  1320. {
  1321. char szBlockName[SIZE_BLOCK_NAME_BUF];
  1322. StartBlock( szBlockName );
  1323. }
  1324. //-------------------------------------
  1325. void CRestore::EndBlock()
  1326. {
  1327. int endPos = m_BlockEndStack[ m_BlockEndStack.Count() - 1 ];
  1328. m_BlockEndStack.Remove( m_BlockEndStack.Count() - 1 );
  1329. SetReadPos( endPos );
  1330. }
  1331. //-------------------------------------
  1332. int CRestore::ReadFields( const char *pname, void *pBaseData, datamap_t *pRootMap, typedescription_t *pFields, int fieldCount )
  1333. {
  1334. static int lastName = -1;
  1335. Verify( ReadShort() == sizeof(int) ); // First entry should be an int
  1336. int symName = m_pData->FindCreateSymbol(pname);
  1337. // Check the struct name
  1338. int curSym = ReadShort();
  1339. if ( curSym != symName ) // Field Set marker
  1340. {
  1341. const char *pLastName = m_pData->StringFromSymbol( lastName );
  1342. const char *pCurName = m_pData->StringFromSymbol( curSym );
  1343. Msg( "Expected %s found %s ( raw '%s' )! (prev: %s)\n", pname, pCurName, BufferPointer(), pLastName );
  1344. Msg( "Field type name may have changed or inheritance graph changed, save file is suspect\n" );
  1345. m_pData->Rewind( 2*sizeof(short) );
  1346. return 0;
  1347. }
  1348. lastName = symName;
  1349. // Clear out base data
  1350. EmptyFields( pBaseData, pFields, fieldCount );
  1351. // Skip over the struct name
  1352. int i;
  1353. int nFieldsSaved = ReadInt(); // Read field count
  1354. int searchCookie = 0; // Make searches faster, most data is read/written in the same order
  1355. SaveRestoreRecordHeader_t header;
  1356. for ( i = 0; i < nFieldsSaved; i++ )
  1357. {
  1358. ReadHeader( &header );
  1359. typedescription_t *pField = FindField( m_pData->StringFromSymbol( header.symbol ), pFields, fieldCount, &searchCookie);
  1360. if ( pField && ShouldReadField( pField ) )
  1361. {
  1362. ReadField( header, ((char *)pBaseData + pField->fieldOffset[ TD_OFFSET_NORMAL ]), pRootMap, pField );
  1363. }
  1364. else
  1365. {
  1366. BufferSkipBytes( header.size ); // Advance to next field
  1367. }
  1368. }
  1369. return 1;
  1370. }
  1371. //-------------------------------------
  1372. void CRestore::ReadHeader( SaveRestoreRecordHeader_t *pheader )
  1373. {
  1374. if ( pheader != NULL )
  1375. {
  1376. Assert( pheader!=NULL );
  1377. pheader->size = ReadShort(); // Read field size
  1378. pheader->symbol = ReadShort(); // Read field name token
  1379. }
  1380. else
  1381. {
  1382. BufferSkipBytes( sizeof(short) * 2 );
  1383. }
  1384. }
  1385. //-------------------------------------
  1386. short CRestore::ReadShort( void )
  1387. {
  1388. short tmp = 0;
  1389. BufferReadBytes( (char *)&tmp, sizeof(short) );
  1390. return tmp;
  1391. }
  1392. //-------------------------------------
  1393. int CRestore::ReadInt( void )
  1394. {
  1395. int tmp = 0;
  1396. BufferReadBytes( (char *)&tmp, sizeof(int) );
  1397. return tmp;
  1398. }
  1399. //-------------------------------------
  1400. // Purpose: Recursively restores all the classes in an object, in reverse order (top down)
  1401. // Output : int 0 on failure, 1 on success
  1402. int CRestore::DoReadAll( void *pLeafObject, datamap_t *pLeafMap, datamap_t *pCurMap )
  1403. {
  1404. // restore base classes first
  1405. if ( pCurMap->baseMap )
  1406. {
  1407. int status = DoReadAll( pLeafObject, pLeafMap, pCurMap->baseMap );
  1408. if ( !status )
  1409. return status;
  1410. }
  1411. return ReadFields( pCurMap->dataClassName, pLeafObject, pLeafMap, pCurMap->dataDesc, pCurMap->dataNumFields );
  1412. }
  1413. //-------------------------------------
  1414. char *CRestore::BufferPointer( void )
  1415. {
  1416. if ( !m_pData )
  1417. return NULL;
  1418. return m_pData->AccessCurPos();
  1419. }
  1420. //-------------------------------------
  1421. void CRestore::BufferReadBytes( char *pOutput, int size )
  1422. {
  1423. Assert( m_pData !=NULL );
  1424. if ( !m_pData || m_pData->BytesAvailable() == 0 )
  1425. return;
  1426. if ( !m_pData->Read( pOutput, size ) )
  1427. {
  1428. Warning( "Restore underflow!\n" );
  1429. Assert(0);
  1430. }
  1431. }
  1432. //-------------------------------------
  1433. void CRestore::BufferSkipBytes( int bytes )
  1434. {
  1435. BufferReadBytes( NULL, bytes );
  1436. }
  1437. //-------------------------------------
  1438. int CRestore::ReadShort( short *pValue, int nElems, int nBytesAvailable )
  1439. {
  1440. return ReadSimple( pValue, nElems, nBytesAvailable );
  1441. }
  1442. //-------------------------------------
  1443. int CRestore::ReadInt( int *pValue, int nElems, int nBytesAvailable )
  1444. {
  1445. return ReadSimple( pValue, nElems, nBytesAvailable );
  1446. }
  1447. //-------------------------------------
  1448. int CRestore::ReadBool( bool *pValue, int nElems, int nBytesAvailable )
  1449. {
  1450. COMPILE_TIME_ASSERT( sizeof(bool) == sizeof(char) );
  1451. return ReadSimple( pValue, nElems, nBytesAvailable );
  1452. }
  1453. //-------------------------------------
  1454. int CRestore::ReadFloat( float *pValue, int nElems, int nBytesAvailable )
  1455. {
  1456. return ReadSimple( pValue, nElems, nBytesAvailable );
  1457. }
  1458. //-------------------------------------
  1459. int CRestore::ReadData( char *pData, int size, int nBytesAvailable )
  1460. {
  1461. return ReadSimple( pData, size, nBytesAvailable );
  1462. }
  1463. //-------------------------------------
  1464. void CRestore::ReadString( char *pDest, int nSizeDest, int nBytesAvailable )
  1465. {
  1466. const char *pString = BufferPointer();
  1467. if ( !nBytesAvailable )
  1468. nBytesAvailable = strlen( pString ) + 1;
  1469. BufferSkipBytes( nBytesAvailable );
  1470. Q_strncpy(pDest, pString, nSizeDest );
  1471. }
  1472. //-------------------------------------
  1473. int CRestore::ReadString( string_t *pValue, int nElems, int nBytesAvailable )
  1474. {
  1475. AssertMsg( nBytesAvailable > 0, "CRestore::ReadString() implementation does not currently support unspecified bytes available");
  1476. int i;
  1477. char *pString = BufferPointer();
  1478. char *pLimit = pString + nBytesAvailable;
  1479. for ( i = 0; i < nElems && pString < pLimit; i++ )
  1480. {
  1481. if ( *((char *)pString) == 0 )
  1482. pValue[i] = NULL_STRING;
  1483. else
  1484. pValue[i] = AllocPooledString( (char *)pString );
  1485. while (*pString)
  1486. pString++;
  1487. pString++;
  1488. }
  1489. BufferSkipBytes( nBytesAvailable );
  1490. return i;
  1491. }
  1492. //-------------------------------------
  1493. int CRestore::ReadVector( Vector *pValue)
  1494. {
  1495. BufferReadBytes( (char *)pValue, sizeof(Vector) );
  1496. return 1;
  1497. }
  1498. //-------------------------------------
  1499. int CRestore::ReadVector( Vector *pValue, int nElems, int nBytesAvailable )
  1500. {
  1501. return ReadSimple( pValue, nElems, nBytesAvailable );
  1502. }
  1503. int CRestore::ReadQuaternion( Quaternion *pValue)
  1504. {
  1505. BufferReadBytes( (char *)pValue, sizeof(Quaternion) );
  1506. return 1;
  1507. }
  1508. //-------------------------------------
  1509. int CRestore::ReadQuaternion( Quaternion *pValue, int nElems, int nBytesAvailable )
  1510. {
  1511. return ReadSimple( pValue, nElems, nBytesAvailable );
  1512. }
  1513. //-------------------------------------
  1514. int CRestore::ReadVMatrix( VMatrix *pValue, int nElems, int nBytesAvailable )
  1515. {
  1516. return ReadSimple( pValue, nElems, nBytesAvailable );
  1517. }
  1518. int CRestore::ReadVMatrixWorldspace( VMatrix *pValue, int nElems, int nBytesAvailable )
  1519. {
  1520. Vector basePosition = m_pGameInfo->GetLandmark();
  1521. VMatrix tmp;
  1522. for ( int i = 0; i < nElems; i++ )
  1523. {
  1524. BufferReadBytes( (char *)&tmp, sizeof(float)*16 );
  1525. VMatrixOffset( pValue[i], tmp, basePosition );
  1526. }
  1527. return nElems;
  1528. }
  1529. int CRestore::ReadMatrix3x4Worldspace( matrix3x4_t *pValue, int nElems, int nBytesAvailable )
  1530. {
  1531. Vector basePosition = m_pGameInfo->GetLandmark();
  1532. matrix3x4_t tmp;
  1533. for ( int i = 0; i < nElems; i++ )
  1534. {
  1535. BufferReadBytes( (char *)&tmp, sizeof(matrix3x4_t) );
  1536. Matrix3x4Offset( pValue[i], tmp, basePosition );
  1537. }
  1538. return nElems;
  1539. }
  1540. int CRestore::ReadInterval( interval_t *interval, int count, int nBytesAvailable )
  1541. {
  1542. return ReadSimple( interval, count, nBytesAvailable );
  1543. }
  1544. //---------------------------------------------------------
  1545. //
  1546. // Game centric restore methods
  1547. //
  1548. CBaseEntity *CRestore::EntityFromIndex( int entityIndex )
  1549. {
  1550. if ( !m_pGameInfo || entityIndex < 0 )
  1551. return NULL;
  1552. int i;
  1553. entitytable_t *pTable;
  1554. for ( i = 0; i < m_pGameInfo->NumEntities(); i++ )
  1555. {
  1556. pTable = m_pGameInfo->GetEntityInfo( i );
  1557. if ( pTable->id == entityIndex )
  1558. return pTable->hEnt;
  1559. }
  1560. return NULL;
  1561. }
  1562. //-------------------------------------
  1563. int CRestore::ReadEntityPtr( CBaseEntity **ppEntity, int count, int nBytesAvailable )
  1564. {
  1565. AssertMsg( count <= MAX_ENTITYARRAY, "Array of entities or ehandles exceeds limit supported by save/restore" );
  1566. int entityArray[MAX_ENTITYARRAY];
  1567. int nRead = ReadInt( entityArray, count, nBytesAvailable );
  1568. for ( int i = 0; i < nRead; i++ ) // nRead is never greater than count
  1569. {
  1570. ppEntity[i] = EntityFromIndex( entityArray[i] );
  1571. }
  1572. if ( nRead < count)
  1573. {
  1574. memset( &ppEntity[nRead], 0, ( count - nRead ) * sizeof(ppEntity[0]) );
  1575. }
  1576. return nRead;
  1577. }
  1578. //-------------------------------------
  1579. int CRestore::ReadEdictPtr( edict_t **ppEdict, int count, int nBytesAvailable )
  1580. {
  1581. #if !defined( CLIENT_DLL )
  1582. AssertMsg( count <= MAX_ENTITYARRAY, "Array of entities or ehandles exceeds limit supported by save/restore" );
  1583. int entityArray[MAX_ENTITYARRAY];
  1584. CBaseEntity *pEntity;
  1585. int nRead = ReadInt( entityArray, count, nBytesAvailable );
  1586. for ( int i = 0; i < nRead; i++ ) // nRead is never greater than count
  1587. {
  1588. pEntity = EntityFromIndex( entityArray[i] );
  1589. ppEdict[i] = (pEntity) ? pEntity->edict() : NULL;
  1590. }
  1591. if ( nRead < count)
  1592. {
  1593. memset( &ppEdict[nRead], 0, ( count - nRead ) * sizeof(ppEdict[0]) );
  1594. }
  1595. return nRead;
  1596. #else
  1597. return 0;
  1598. #endif
  1599. }
  1600. //-------------------------------------
  1601. int CRestore::ReadEHandle( EHANDLE *pEHandle, int count, int nBytesAvailable )
  1602. {
  1603. AssertMsg( count <= MAX_ENTITYARRAY, "Array of entities or ehandles exceeds limit supported by save/restore" );
  1604. int entityArray[MAX_ENTITYARRAY];
  1605. int nRead = ReadInt( entityArray, count, nBytesAvailable );
  1606. for ( int i = 0; i < nRead; i++ ) // nRead is never greater than count
  1607. {
  1608. pEHandle[i] = EntityFromIndex( entityArray[i] );
  1609. }
  1610. if ( nRead < count)
  1611. {
  1612. memset( &pEHandle[nRead], 0xFF, ( count - nRead ) * sizeof(pEHandle[0]) );
  1613. }
  1614. return nRead;
  1615. }
  1616. //-------------------------------------
  1617. // Purpose: Reads all the fields that are not client neutral. In the event of
  1618. // a librarization of save/restore, these would NOT reside in the library
  1619. void CRestore::ReadGameField( const SaveRestoreRecordHeader_t &header, void *pDest, datamap_t *pRootMap, typedescription_t *pField )
  1620. {
  1621. switch( pField->fieldType )
  1622. {
  1623. case FIELD_POSITION_VECTOR:
  1624. {
  1625. ReadPositionVector( (Vector *)pDest, pField->fieldSize, header.size );
  1626. break;
  1627. }
  1628. case FIELD_TIME:
  1629. {
  1630. ReadTime( (float *)pDest, pField->fieldSize, header.size );
  1631. break;
  1632. }
  1633. case FIELD_TICK:
  1634. {
  1635. ReadTick( (int *)pDest, pField->fieldSize, header.size );
  1636. break;
  1637. }
  1638. case FIELD_FUNCTION:
  1639. {
  1640. ReadFunction( pRootMap, (inputfunc_t **)pDest, pField->fieldSize, header.size );
  1641. break;
  1642. }
  1643. case FIELD_MODELINDEX:
  1644. {
  1645. int *pModelIndex = (int*)pDest;
  1646. string_t *pModelName = (string_t *)stackalloc( pField->fieldSize * sizeof(string_t) );
  1647. int nRead = ReadString( pModelName, pField->fieldSize, header.size );
  1648. for ( int i = 0; i < nRead; i++ )
  1649. {
  1650. if ( pModelName[i] == NULL_STRING )
  1651. {
  1652. pModelIndex[i] = -1;
  1653. continue;
  1654. }
  1655. pModelIndex[i] = modelinfo->GetModelIndex( STRING( pModelName[i] ) );
  1656. #if !defined( CLIENT_DLL )
  1657. if ( m_precache )
  1658. {
  1659. CBaseEntity::PrecacheModel( STRING( pModelName[i] ) );
  1660. }
  1661. #endif
  1662. }
  1663. break;
  1664. }
  1665. case FIELD_MATERIALINDEX:
  1666. {
  1667. int *pMaterialIndex = (int*)pDest;
  1668. string_t *pMaterialName = (string_t *)stackalloc( pField->fieldSize * sizeof(string_t) );
  1669. int nRead = ReadString( pMaterialName, pField->fieldSize, header.size );
  1670. for ( int i = 0; i < nRead; i++ )
  1671. {
  1672. if ( pMaterialName[i] == NULL_STRING )
  1673. {
  1674. pMaterialIndex[i] = 0;
  1675. continue;
  1676. }
  1677. pMaterialIndex[i] = GetMaterialIndex( STRING( pMaterialName[i] ) );
  1678. #if !defined( CLIENT_DLL )
  1679. if ( m_precache )
  1680. {
  1681. PrecacheMaterial( STRING( pMaterialName[i] ) );
  1682. }
  1683. #endif
  1684. }
  1685. break;
  1686. }
  1687. case FIELD_MODELNAME:
  1688. case FIELD_SOUNDNAME:
  1689. {
  1690. string_t *pStringDest = (string_t *)pDest;
  1691. int nRead = ReadString( pStringDest, pField->fieldSize, header.size );
  1692. if ( m_precache )
  1693. {
  1694. #if !defined( CLIENT_DLL )
  1695. // HACKHACK: Rewrite the .bsp models to match the map name in case the bugreporter renamed it
  1696. if ( pField->fieldType == FIELD_MODELNAME && Q_stristr(pStringDest->ToCStr(), ".bsp") )
  1697. {
  1698. char buf[MAX_PATH];
  1699. Q_strncpy( buf, "maps/", sizeof(buf) );
  1700. Q_strncat( buf, gpGlobals->mapname.ToCStr(), sizeof(buf) );
  1701. Q_strncat( buf, ".bsp", sizeof(buf) );
  1702. *pStringDest = AllocPooledString( buf );
  1703. }
  1704. #endif
  1705. for ( int i = 0; i < nRead; i++ )
  1706. {
  1707. if ( pStringDest[i] != NULL_STRING )
  1708. {
  1709. #if !defined( CLIENT_DLL )
  1710. if ( pField->fieldType == FIELD_MODELNAME )
  1711. {
  1712. CBaseEntity::PrecacheModel( STRING( pStringDest[i] ) );
  1713. }
  1714. else if ( pField->fieldType == FIELD_SOUNDNAME )
  1715. {
  1716. CBaseEntity::PrecacheScriptSound( STRING( pStringDest[i] ) );
  1717. }
  1718. #endif
  1719. }
  1720. }
  1721. }
  1722. break;
  1723. }
  1724. case FIELD_CLASSPTR:
  1725. ReadEntityPtr( (CBaseEntity **)pDest, pField->fieldSize, header.size );
  1726. break;
  1727. case FIELD_EDICT:
  1728. #if !defined( CLIENT_DLL )
  1729. ReadEdictPtr( (edict_t **)pDest, pField->fieldSize, header.size );
  1730. #else
  1731. Assert( !"FIELD_EDICT not valid for client .dll" );
  1732. #endif
  1733. break;
  1734. case FIELD_EHANDLE:
  1735. ReadEHandle( (EHANDLE *)pDest, pField->fieldSize, header.size );
  1736. break;
  1737. case FIELD_VMATRIX:
  1738. {
  1739. ReadVMatrix( (VMatrix *)pDest, pField->fieldSize, header.size );
  1740. break;
  1741. }
  1742. case FIELD_VMATRIX_WORLDSPACE:
  1743. ReadVMatrixWorldspace( (VMatrix *)pDest, pField->fieldSize, header.size );
  1744. break;
  1745. case FIELD_MATRIX3X4_WORLDSPACE:
  1746. ReadMatrix3x4Worldspace( (matrix3x4_t *)pDest, pField->fieldSize, header.size );
  1747. break;
  1748. case FIELD_INTERVAL:
  1749. ReadInterval( (interval_t *)pDest, pField->fieldSize, header.size );
  1750. break;
  1751. default:
  1752. Warning( "Bad field type\n" );
  1753. Assert(0);
  1754. }
  1755. }
  1756. //-------------------------------------
  1757. int CRestore::ReadTime( float *pValue, int count, int nBytesAvailable )
  1758. {
  1759. float baseTime = m_pGameInfo->GetBaseTime();
  1760. int nRead = ReadFloat( pValue, count, nBytesAvailable );
  1761. for ( int i = nRead - 1; i >= 0; i-- )
  1762. {
  1763. if ( pValue[i] == ZERO_TIME )
  1764. pValue[i] = 0.0;
  1765. else if ( pValue[i] != INVALID_TIME && pValue[i] != FLT_MAX )
  1766. pValue[i] += baseTime;
  1767. }
  1768. return nRead;
  1769. }
  1770. int CRestore::ReadTick( int *pValue, int count, int nBytesAvailable )
  1771. {
  1772. // HACK HACK: Adding 0.1f here makes sure that all tick times read
  1773. // from .sav file which are near the basetime will end up just ahead of
  1774. // the base time, because we are restoring we'll have a slow frame of the
  1775. // max frametime of 0.1 seconds and that could otherwise cause all of our
  1776. // think times to get synchronized to each other... sigh. ywb...
  1777. int baseTick = TIME_TO_TICKS( m_pGameInfo->GetBaseTime() + 0.1f );
  1778. int nRead = ReadInt( pValue, count, nBytesAvailable );
  1779. for ( int i = nRead - 1; i >= 0; i-- )
  1780. {
  1781. if ( pValue[ i ] != TICK_NEVER_THINK_ENCODE )
  1782. {
  1783. // Rebase it
  1784. pValue[i] += baseTick;
  1785. }
  1786. else
  1787. {
  1788. // Slam to -1 value
  1789. pValue[ i ] = TICK_NEVER_THINK;
  1790. }
  1791. }
  1792. return nRead;
  1793. }
  1794. //-------------------------------------
  1795. int CRestore::ReadPositionVector( Vector *pValue )
  1796. {
  1797. return ReadPositionVector( pValue, 1, sizeof(Vector) );
  1798. }
  1799. //-------------------------------------
  1800. int CRestore::ReadPositionVector( Vector *pValue, int count, int nBytesAvailable )
  1801. {
  1802. Vector basePosition = m_pGameInfo->GetLandmark();
  1803. int nRead = ReadVector( pValue, count, nBytesAvailable );
  1804. for ( int i = nRead - 1; i >= 0; i-- )
  1805. {
  1806. if ( pValue[i] != vec3_invalid )
  1807. pValue[i] += basePosition;
  1808. }
  1809. return nRead;
  1810. }
  1811. //-------------------------------------
  1812. int CRestore::ReadFunction( datamap_t *pMap, inputfunc_t **pValue, int count, int nBytesAvailable )
  1813. {
  1814. AssertMsg( nBytesAvailable > 0, "CRestore::ReadFunction() implementation does not currently support unspecified bytes available");
  1815. char *pszFunctionName = BufferPointer();
  1816. BufferSkipBytes( nBytesAvailable );
  1817. AssertMsg( count == 1, "Arrays of functions not presently supported" );
  1818. if ( *pszFunctionName == 0 )
  1819. *pValue = NULL;
  1820. else
  1821. *pValue = UTIL_FunctionFromName( pMap, pszFunctionName );
  1822. return 0;
  1823. }
  1824. //-----------------------------------------------------------------------------
  1825. //
  1826. // Entity data saving routines
  1827. //
  1828. //-----------------------------------------------------------------------------
  1829. BEGIN_SIMPLE_DATADESC(entitytable_t)
  1830. DEFINE_FIELD( id, FIELD_INTEGER ),
  1831. DEFINE_FIELD( edictindex, FIELD_INTEGER ),
  1832. DEFINE_FIELD( saveentityindex, FIELD_INTEGER ),
  1833. // DEFINE_FIELD( restoreentityindex, FIELD_INTEGER ),
  1834. // hEnt (not saved, this is the fixup)
  1835. DEFINE_FIELD( location, FIELD_INTEGER ),
  1836. DEFINE_FIELD( size, FIELD_INTEGER ),
  1837. DEFINE_FIELD( flags, FIELD_INTEGER ),
  1838. DEFINE_FIELD( classname, FIELD_STRING ),
  1839. DEFINE_FIELD( globalname, FIELD_STRING ),
  1840. DEFINE_FIELD( landmarkModelSpace, FIELD_VECTOR ),
  1841. DEFINE_FIELD( modelname, FIELD_STRING ),
  1842. END_DATADESC()
  1843. //-----------------------------------------------------------------------------
  1844. // Utilities entities can use when saving
  1845. //-----------------------------------------------------------------------------
  1846. class CEntitySaveUtils : public IEntitySaveUtils
  1847. {
  1848. public:
  1849. // Call these in pre-save + post save
  1850. void PreSave();
  1851. void PostSave();
  1852. // Methods of IEntitySaveUtils
  1853. virtual void AddLevelTransitionSaveDependency( CBaseEntity *pEntity1, CBaseEntity *pEntity2 );
  1854. virtual int GetEntityDependencyCount( CBaseEntity *pEntity );
  1855. virtual int GetEntityDependencies( CBaseEntity *pEntity, int nCount, CBaseEntity **ppEntList );
  1856. private:
  1857. IPhysicsObjectPairHash *m_pLevelAdjacencyDependencyHash;
  1858. };
  1859. //-----------------------------------------------------------------------------
  1860. // Call these in pre-save + post save
  1861. //-----------------------------------------------------------------------------
  1862. void CEntitySaveUtils::PreSave()
  1863. {
  1864. Assert( !m_pLevelAdjacencyDependencyHash );
  1865. MEM_ALLOC_CREDIT();
  1866. m_pLevelAdjacencyDependencyHash = physics->CreateObjectPairHash();
  1867. }
  1868. void CEntitySaveUtils::PostSave()
  1869. {
  1870. physics->DestroyObjectPairHash( m_pLevelAdjacencyDependencyHash );
  1871. m_pLevelAdjacencyDependencyHash = NULL;
  1872. }
  1873. //-----------------------------------------------------------------------------
  1874. // Gets the # of dependencies for a particular entity
  1875. //-----------------------------------------------------------------------------
  1876. int CEntitySaveUtils::GetEntityDependencyCount( CBaseEntity *pEntity )
  1877. {
  1878. return m_pLevelAdjacencyDependencyHash->GetPairCountForObject( pEntity );
  1879. }
  1880. //-----------------------------------------------------------------------------
  1881. // Gets all dependencies for a particular entity
  1882. //-----------------------------------------------------------------------------
  1883. int CEntitySaveUtils::GetEntityDependencies( CBaseEntity *pEntity, int nCount, CBaseEntity **ppEntList )
  1884. {
  1885. return m_pLevelAdjacencyDependencyHash->GetPairListForObject( pEntity, nCount, (void**)ppEntList );
  1886. }
  1887. //-----------------------------------------------------------------------------
  1888. // Methods of IEntitySaveUtils
  1889. //-----------------------------------------------------------------------------
  1890. void CEntitySaveUtils::AddLevelTransitionSaveDependency( CBaseEntity *pEntity1, CBaseEntity *pEntity2 )
  1891. {
  1892. if ( pEntity1 != pEntity2 )
  1893. {
  1894. m_pLevelAdjacencyDependencyHash->AddObjectPair( pEntity1, pEntity2 );
  1895. }
  1896. }
  1897. //-----------------------------------------------------------------------------
  1898. // Block handler for save/restore of entities
  1899. //-----------------------------------------------------------------------------
  1900. class CEntitySaveRestoreBlockHandler : public ISaveRestoreBlockHandler
  1901. {
  1902. public:
  1903. const char *GetBlockName();
  1904. void PreSave( CSaveRestoreData *pSaveData );
  1905. void Save( ISave *pSave );
  1906. void WriteSaveHeaders( ISave *pSave );
  1907. virtual void PostSave();
  1908. virtual void PreRestore();
  1909. void ReadRestoreHeaders( IRestore *pRestore );
  1910. void Restore( IRestore *pRestore, bool createPlayers );
  1911. virtual void PostRestore();
  1912. inline IEntitySaveUtils * GetEntitySaveUtils() { return &m_EntitySaveUtils; }
  1913. private:
  1914. friend int CreateEntityTransitionList( CSaveRestoreData *pSaveData, int levelMask );
  1915. bool SaveInitEntities( CSaveRestoreData *pSaveData );
  1916. bool DoRestoreEntity( CBaseEntity *pEntity, IRestore *pRestore );
  1917. Vector ModelSpaceLandmark( int modelIndex );
  1918. int RestoreEntity( CBaseEntity *pEntity, IRestore *pRestore, entitytable_t *pEntInfo );
  1919. #if !defined( CLIENT_DLL )
  1920. // Find the matching global entity. Spit out an error if the designer made entities of
  1921. // different classes with the same global name
  1922. CBaseEntity *FindGlobalEntity( string_t classname, string_t globalname );
  1923. int RestoreGlobalEntity( CBaseEntity *pEntity, CSaveRestoreData *pSaveData, entitytable_t *pEntInfo );
  1924. #endif
  1925. private:
  1926. CEntitySaveUtils m_EntitySaveUtils;
  1927. };
  1928. //-----------------------------------------------------------------------------
  1929. CEntitySaveRestoreBlockHandler g_EntitySaveRestoreBlockHandler;
  1930. //-------------------------------------
  1931. ISaveRestoreBlockHandler *GetEntitySaveRestoreBlockHandler()
  1932. {
  1933. return &g_EntitySaveRestoreBlockHandler;
  1934. }
  1935. IEntitySaveUtils *GetEntitySaveUtils()
  1936. {
  1937. return g_EntitySaveRestoreBlockHandler.GetEntitySaveUtils();
  1938. }
  1939. //-----------------------------------------------------------------------------
  1940. // Implementation of the block handler for save/restore of entities
  1941. //-----------------------------------------------------------------------------
  1942. const char *CEntitySaveRestoreBlockHandler::GetBlockName()
  1943. {
  1944. return "Entities";
  1945. }
  1946. //---------------------------------
  1947. void CEntitySaveRestoreBlockHandler::PreSave( CSaveRestoreData *pSaveData )
  1948. {
  1949. MDLCACHE_CRITICAL_SECTION();
  1950. IGameSystem::OnSaveAllSystems();
  1951. m_EntitySaveUtils.PreSave();
  1952. // Allow the entities to do some work
  1953. CBaseEntity *pEnt = NULL;
  1954. #if !defined( CLIENT_DLL )
  1955. while ( (pEnt = gEntList.NextEnt( pEnt )) != NULL )
  1956. {
  1957. pEnt->OnSave( &m_EntitySaveUtils );
  1958. }
  1959. #else
  1960. // Do this because it'll force entities to figure out their origins, and that requires
  1961. // SetupBones in the case of aiments.
  1962. {
  1963. C_BaseAnimating::AutoAllowBoneAccess boneaccess( true, true );
  1964. int last = ClientEntityList().GetHighestEntityIndex();
  1965. ClientEntityHandle_t iter = ClientEntityList().FirstHandle();
  1966. for ( int e = 0; e <= last; e++ )
  1967. {
  1968. pEnt = ClientEntityList().GetBaseEntity( e );
  1969. if( !pEnt )
  1970. continue;
  1971. pEnt->OnSave();
  1972. }
  1973. while ( iter != ClientEntityList().InvalidHandle() )
  1974. {
  1975. pEnt = ClientEntityList().GetBaseEntityFromHandle( iter );
  1976. if ( pEnt && pEnt->ObjectCaps() & FCAP_SAVE_NON_NETWORKABLE )
  1977. {
  1978. pEnt->OnSave();
  1979. }
  1980. iter = ClientEntityList().NextHandle( iter );
  1981. }
  1982. }
  1983. #endif
  1984. SaveInitEntities( pSaveData );
  1985. }
  1986. //---------------------------------
  1987. void CEntitySaveRestoreBlockHandler::Save( ISave *pSave )
  1988. {
  1989. CGameSaveRestoreInfo *pSaveData = pSave->GetGameSaveRestoreInfo();
  1990. // write entity list that was previously built by SaveInitEntities()
  1991. for ( int i = 0; i < pSaveData->NumEntities(); i++ )
  1992. {
  1993. entitytable_t *pEntInfo = pSaveData->GetEntityInfo( i );
  1994. pEntInfo->location = pSave->GetWritePos();
  1995. pEntInfo->size = 0;
  1996. CBaseEntity *pEnt = pEntInfo->hEnt;
  1997. if ( pEnt && !( pEnt->ObjectCaps() & FCAP_DONT_SAVE ) )
  1998. {
  1999. MDLCACHE_CRITICAL_SECTION();
  2000. #if !defined( CLIENT_DLL )
  2001. AssertMsg( !pEnt->edict() || ( pEnt->m_iClassname != NULL_STRING &&
  2002. (STRING(pEnt->m_iClassname)[0] != 0) &&
  2003. FStrEq( STRING(pEnt->m_iClassname), pEnt->GetClassname()) ),
  2004. "Saving entity with invalid classname" );
  2005. #endif
  2006. pSaveData->SetCurrentEntityContext( pEnt );
  2007. pEnt->Save( *pSave );
  2008. pSaveData->SetCurrentEntityContext( NULL );
  2009. pEntInfo->size = pSave->GetWritePos() - pEntInfo->location; // Size of entity block is data size written to block
  2010. pEntInfo->classname = pEnt->m_iClassname; // Remember entity class for respawn
  2011. #if !defined( CLIENT_DLL )
  2012. pEntInfo->globalname = pEnt->m_iGlobalname; // remember global name
  2013. pEntInfo->landmarkModelSpace = ModelSpaceLandmark( pEnt->GetModelIndex() );
  2014. int nEntIndex = pEnt->edict() ? ENTINDEX(pEnt->edict()) : -1;
  2015. bool bIsPlayer = ( ( nEntIndex >= 1 ) && ( nEntIndex <= gpGlobals->maxClients ) ) ? true : false;
  2016. if ( bIsPlayer )
  2017. {
  2018. pEntInfo->flags |= FENTTABLE_PLAYER;
  2019. }
  2020. #endif
  2021. }
  2022. }
  2023. }
  2024. //---------------------------------
  2025. void CEntitySaveRestoreBlockHandler::WriteSaveHeaders( ISave *pSave )
  2026. {
  2027. CGameSaveRestoreInfo *pSaveData = pSave->GetGameSaveRestoreInfo();
  2028. int nEntities = pSaveData->NumEntities();
  2029. pSave->WriteInt( &nEntities );
  2030. for ( int i = 0; i < pSaveData->NumEntities(); i++ )
  2031. pSave->WriteFields( "ETABLE", pSaveData->GetEntityInfo( i ), NULL, entitytable_t::m_DataMap.dataDesc, entitytable_t::m_DataMap.dataNumFields );
  2032. }
  2033. //---------------------------------
  2034. void CEntitySaveRestoreBlockHandler::PostSave()
  2035. {
  2036. m_EntitySaveUtils.PostSave();
  2037. }
  2038. //---------------------------------
  2039. void CEntitySaveRestoreBlockHandler::PreRestore()
  2040. {
  2041. }
  2042. //---------------------------------
  2043. void CEntitySaveRestoreBlockHandler::ReadRestoreHeaders( IRestore *pRestore )
  2044. {
  2045. CGameSaveRestoreInfo *pSaveData = pRestore->GetGameSaveRestoreInfo();
  2046. int nEntities;
  2047. pRestore->ReadInt( &nEntities );
  2048. entitytable_t *pEntityTable = ( entitytable_t *)engine->SaveAllocMemory( (sizeof(entitytable_t) * nEntities), sizeof(char) );
  2049. if ( !pEntityTable )
  2050. {
  2051. return;
  2052. }
  2053. pSaveData->InitEntityTable( pEntityTable, nEntities );
  2054. for ( int i = 0; i < pSaveData->NumEntities(); i++ )
  2055. pRestore->ReadFields( "ETABLE", pSaveData->GetEntityInfo( i ), NULL, entitytable_t::m_DataMap.dataDesc, entitytable_t::m_DataMap.dataNumFields );
  2056. }
  2057. //---------------------------------
  2058. #if !defined( CLIENT_DLL )
  2059. void CEntitySaveRestoreBlockHandler::Restore( IRestore *pRestore, bool createPlayers )
  2060. {
  2061. entitytable_t *pEntInfo;
  2062. CBaseEntity *pent;
  2063. CGameSaveRestoreInfo *pSaveData = pRestore->GetGameSaveRestoreInfo();
  2064. bool restoredWorld = false;
  2065. // Create entity list
  2066. int i;
  2067. for ( i = 0; i < pSaveData->NumEntities(); i++ )
  2068. {
  2069. pEntInfo = pSaveData->GetEntityInfo( i );
  2070. if ( pEntInfo->classname != NULL_STRING && pEntInfo->size && !(pEntInfo->flags & FENTTABLE_REMOVED) )
  2071. {
  2072. if ( pEntInfo->edictindex == 0 ) // worldspawn
  2073. {
  2074. Assert( i == 0 );
  2075. pent = CreateEntityByName( STRING(pEntInfo->classname) );
  2076. pRestore->SetReadPos( pEntInfo->location );
  2077. if ( RestoreEntity( pent, pRestore, pEntInfo ) < 0 )
  2078. {
  2079. pEntInfo->hEnt = NULL;
  2080. pEntInfo->restoreentityindex = -1;
  2081. UTIL_RemoveImmediate( pent );
  2082. }
  2083. else
  2084. {
  2085. // force the entity to be relinked
  2086. AddRestoredEntity( pent );
  2087. }
  2088. }
  2089. else if ( (pEntInfo->edictindex > 0) && (pEntInfo->edictindex <= gpGlobals->maxClients) )
  2090. {
  2091. if ( !(pEntInfo->flags & FENTTABLE_PLAYER) )
  2092. {
  2093. Warning( "ENTITY IS NOT A PLAYER: %d\n" , i );
  2094. Assert(0);
  2095. }
  2096. edict_t *ed = INDEXENT( pEntInfo->edictindex );
  2097. if ( ed && createPlayers )
  2098. {
  2099. // create the player
  2100. pent = CBasePlayer::CreatePlayer( STRING(pEntInfo->classname), ed );
  2101. }
  2102. else
  2103. pent = NULL;
  2104. }
  2105. else
  2106. {
  2107. pent = CreateEntityByName( STRING(pEntInfo->classname) );
  2108. }
  2109. pEntInfo->hEnt = pent;
  2110. pEntInfo->restoreentityindex = pent ? pent->entindex() : - 1;
  2111. if ( pent && pEntInfo->restoreentityindex == 0 )
  2112. {
  2113. if ( !FClassnameIs( pent, "worldspawn" ) )
  2114. {
  2115. pEntInfo->restoreentityindex = -1;
  2116. }
  2117. }
  2118. if ( pEntInfo->restoreentityindex == 0 )
  2119. {
  2120. Assert( !restoredWorld );
  2121. restoredWorld = true;
  2122. }
  2123. }
  2124. else
  2125. {
  2126. pEntInfo->hEnt = NULL;
  2127. pEntInfo->restoreentityindex = -1;
  2128. }
  2129. }
  2130. // Now spawn entities
  2131. for ( i = 0; i < pSaveData->NumEntities(); i++ )
  2132. {
  2133. pEntInfo = pSaveData->GetEntityInfo( i );
  2134. if ( pEntInfo->edictindex != 0 )
  2135. {
  2136. pent = pEntInfo->hEnt;
  2137. pRestore->SetReadPos( pEntInfo->location );
  2138. if ( pent )
  2139. {
  2140. if ( RestoreEntity( pent, pRestore, pEntInfo ) < 0 )
  2141. {
  2142. pEntInfo->hEnt = NULL;
  2143. pEntInfo->restoreentityindex = -1;
  2144. UTIL_RemoveImmediate( pent );
  2145. }
  2146. else
  2147. {
  2148. AddRestoredEntity( pent );
  2149. }
  2150. }
  2151. }
  2152. }
  2153. }
  2154. #else // CLIENT DLL VERSION
  2155. void CEntitySaveRestoreBlockHandler::Restore( IRestore *pRestore, bool createPlayers )
  2156. {
  2157. entitytable_t *pEntInfo;
  2158. CBaseEntity *pent;
  2159. CGameSaveRestoreInfo *pSaveData = pRestore->GetGameSaveRestoreInfo();
  2160. // Create entity list
  2161. int i;
  2162. bool restoredWorld = false;
  2163. for ( i = 0; i < pSaveData->NumEntities(); i++ )
  2164. {
  2165. pEntInfo = pSaveData->GetEntityInfo( i );
  2166. pent = ClientEntityList().GetBaseEntity( pEntInfo->restoreentityindex );
  2167. pEntInfo->hEnt = pent;
  2168. }
  2169. // Blast saved data into entities
  2170. for ( i = 0; i < pSaveData->NumEntities(); i++ )
  2171. {
  2172. pEntInfo = pSaveData->GetEntityInfo( i );
  2173. bool bRestoredCorrectly = false;
  2174. // FIXME, need to translate save spot to real index here using lookup table transmitted from server
  2175. //Assert( !"Need translation still" );
  2176. if ( pEntInfo->restoreentityindex >= 0 )
  2177. {
  2178. if ( pEntInfo->restoreentityindex == 0 )
  2179. {
  2180. Assert( !restoredWorld );
  2181. restoredWorld = true;
  2182. }
  2183. pent = ClientEntityList().GetBaseEntity( pEntInfo->restoreentityindex );
  2184. pRestore->SetReadPos( pEntInfo->location );
  2185. if ( pent )
  2186. {
  2187. if ( RestoreEntity( pent, pRestore, pEntInfo ) >= 0 )
  2188. {
  2189. // Call the OnRestore method
  2190. AddRestoredEntity( pent );
  2191. bRestoredCorrectly = true;
  2192. }
  2193. }
  2194. }
  2195. // BUGBUG: JAY: Disable ragdolls across transitions until PVS/solid check & client entity patch file are implemented
  2196. else if ( !pSaveData->levelInfo.fUseLandmark )
  2197. {
  2198. if ( pEntInfo->classname != NULL_STRING )
  2199. {
  2200. pent = CreateEntityByName( STRING(pEntInfo->classname) );
  2201. pent->InitializeAsClientEntity( NULL, RENDER_GROUP_OPAQUE_ENTITY );
  2202. pRestore->SetReadPos( pEntInfo->location );
  2203. if ( pent )
  2204. {
  2205. if ( RestoreEntity( pent, pRestore, pEntInfo ) >= 0 )
  2206. {
  2207. pEntInfo->hEnt = pent;
  2208. AddRestoredEntity( pent );
  2209. bRestoredCorrectly = true;
  2210. }
  2211. }
  2212. }
  2213. }
  2214. if ( !bRestoredCorrectly )
  2215. {
  2216. pEntInfo->hEnt = NULL;
  2217. pEntInfo->restoreentityindex = -1;
  2218. }
  2219. }
  2220. // Note, server does this after local player connects fully
  2221. IGameSystem::OnRestoreAllSystems();
  2222. // Tell hud elements to modify behavior based on game restoration, if applicable
  2223. gHUD.OnRestore();
  2224. }
  2225. #endif
  2226. void CEntitySaveRestoreBlockHandler::PostRestore()
  2227. {
  2228. }
  2229. void SaveEntityOnTable( CBaseEntity *pEntity, CSaveRestoreData *pSaveData, int &iSlot )
  2230. {
  2231. entitytable_t *pEntInfo = pSaveData->GetEntityInfo( iSlot );
  2232. pEntInfo->id = iSlot;
  2233. #if !defined( CLIENT_DLL )
  2234. pEntInfo->edictindex = pEntity->RequiredEdictIndex();
  2235. #else
  2236. pEntInfo->edictindex = -1;
  2237. #endif
  2238. pEntInfo->modelname = pEntity->GetModelName();
  2239. pEntInfo->restoreentityindex = -1;
  2240. pEntInfo->saveentityindex = pEntity ? pEntity->entindex() : -1;
  2241. pEntInfo->hEnt = pEntity;
  2242. pEntInfo->flags = 0;
  2243. pEntInfo->location = 0;
  2244. pEntInfo->size = 0;
  2245. pEntInfo->classname = NULL_STRING;
  2246. iSlot++;
  2247. }
  2248. //---------------------------------
  2249. bool CEntitySaveRestoreBlockHandler::SaveInitEntities( CSaveRestoreData *pSaveData )
  2250. {
  2251. int number_of_entities;
  2252. #if !defined( CLIENT_DLL )
  2253. number_of_entities = gEntList.NumberOfEntities();
  2254. #else
  2255. number_of_entities = ClientEntityList().NumberOfEntities( true );
  2256. #endif
  2257. entitytable_t *pEntityTable = ( entitytable_t *)engine->SaveAllocMemory( (sizeof(entitytable_t) * number_of_entities), sizeof(char) );
  2258. if ( !pEntityTable )
  2259. return false;
  2260. pSaveData->InitEntityTable( pEntityTable, number_of_entities );
  2261. // build the table of entities
  2262. // this is used to turn pointers into savable indices
  2263. // build up ID numbers for each entity, for use in pointer conversions
  2264. // if an entity requires a certain edict number upon restore, save that as well
  2265. CBaseEntity *pEnt = NULL;
  2266. int i = 0;
  2267. #if !defined( CLIENT_DLL )
  2268. while ( (pEnt = gEntList.NextEnt( pEnt )) != NULL )
  2269. {
  2270. #else
  2271. int last = ClientEntityList().GetHighestEntityIndex();
  2272. for ( int e = 0; e <= last; e++ )
  2273. {
  2274. pEnt = ClientEntityList().GetBaseEntity( e );
  2275. if( !pEnt )
  2276. continue;
  2277. #endif
  2278. SaveEntityOnTable( pEnt, pSaveData, i );
  2279. }
  2280. #if defined( CLIENT_DLL )
  2281. ClientEntityHandle_t iter = ClientEntityList().FirstHandle();
  2282. while ( iter != ClientEntityList().InvalidHandle() )
  2283. {
  2284. pEnt = ClientEntityList().GetBaseEntityFromHandle( iter );
  2285. if ( pEnt && pEnt->ObjectCaps() & FCAP_SAVE_NON_NETWORKABLE )
  2286. {
  2287. SaveEntityOnTable( pEnt, pSaveData, i );
  2288. }
  2289. iter = ClientEntityList().NextHandle( iter );
  2290. }
  2291. #endif
  2292. pSaveData->BuildEntityHash();
  2293. Assert( i == pSaveData->NumEntities() );
  2294. return ( i == pSaveData->NumEntities() );
  2295. }
  2296. //---------------------------------
  2297. #if !defined( CLIENT_DLL )
  2298. // Find the matching global entity. Spit out an error if the designer made entities of
  2299. // different classes with the same global name
  2300. CBaseEntity *CEntitySaveRestoreBlockHandler::FindGlobalEntity( string_t classname, string_t globalname )
  2301. {
  2302. CBaseEntity *pReturn = NULL;
  2303. while ( (pReturn = gEntList.NextEnt( pReturn )) != NULL )
  2304. {
  2305. if ( FStrEq( STRING(pReturn->m_iGlobalname), STRING(globalname)) )
  2306. break;
  2307. }
  2308. if ( pReturn )
  2309. {
  2310. if ( !FClassnameIs( pReturn, STRING(classname) ) )
  2311. {
  2312. Warning( "Global entity found %s, wrong class %s [expects class %s]\n", STRING(globalname), STRING(pReturn->m_iClassname), STRING(classname) );
  2313. pReturn = NULL;
  2314. }
  2315. }
  2316. return pReturn;
  2317. }
  2318. #endif // !defined( CLIENT_DLL )
  2319. //---------------------------------
  2320. bool CEntitySaveRestoreBlockHandler::DoRestoreEntity( CBaseEntity *pEntity, IRestore *pRestore )
  2321. {
  2322. MDLCACHE_CRITICAL_SECTION();
  2323. EHANDLE hEntity;
  2324. hEntity = pEntity;
  2325. pRestore->GetGameSaveRestoreInfo()->SetCurrentEntityContext( pEntity );
  2326. pEntity->Restore( *pRestore );
  2327. pRestore->GetGameSaveRestoreInfo()->SetCurrentEntityContext( NULL );
  2328. #if !defined( CLIENT_DLL )
  2329. if ( pEntity->ObjectCaps() & FCAP_MUST_SPAWN )
  2330. {
  2331. pEntity->Spawn();
  2332. }
  2333. else
  2334. {
  2335. pEntity->Precache( );
  2336. }
  2337. #endif
  2338. // Above calls may have resulted in self destruction
  2339. return ( hEntity != NULL );
  2340. }
  2341. //---------------------------------
  2342. // Get a reference position in model space to compute
  2343. // changes in model space for global brush entities (designer models them in different coords!)
  2344. Vector CEntitySaveRestoreBlockHandler::ModelSpaceLandmark( int modelIndex )
  2345. {
  2346. const model_t *pModel = modelinfo->GetModel( modelIndex );
  2347. if ( modelinfo->GetModelType( pModel ) != mod_brush )
  2348. return vec3_origin;
  2349. Vector mins, maxs;
  2350. modelinfo->GetModelBounds( pModel, mins, maxs );
  2351. return mins;
  2352. }
  2353. int CEntitySaveRestoreBlockHandler::RestoreEntity( CBaseEntity *pEntity, IRestore *pRestore, entitytable_t *pEntInfo )
  2354. {
  2355. if ( !DoRestoreEntity( pEntity, pRestore ) )
  2356. return 0;
  2357. #if !defined( CLIENT_DLL )
  2358. if ( pEntity->m_iGlobalname != NULL_STRING )
  2359. {
  2360. int globalIndex = GlobalEntity_GetIndex( pEntity->m_iGlobalname );
  2361. if ( globalIndex >= 0 )
  2362. {
  2363. // Already dead? delete
  2364. if ( GlobalEntity_GetState( globalIndex ) == GLOBAL_DEAD )
  2365. return -1;
  2366. else if ( !FStrEq( STRING(gpGlobals->mapname), GlobalEntity_GetMap(globalIndex) ) )
  2367. {
  2368. pEntity->MakeDormant(); // Hasn't been moved to this level yet, wait but stay alive
  2369. }
  2370. // In this level & not dead, continue on as normal
  2371. }
  2372. else
  2373. {
  2374. Warning( "Global Entity %s (%s) not in table!!!\n", STRING(pEntity->m_iGlobalname), STRING(pEntity->m_iClassname) );
  2375. // Spawned entities default to 'On'
  2376. GlobalEntity_Add( pEntity->m_iGlobalname, gpGlobals->mapname, GLOBAL_ON );
  2377. }
  2378. }
  2379. #endif
  2380. return 0;
  2381. }
  2382. //---------------------------------
  2383. #if !defined( CLIENT_DLL )
  2384. int CEntitySaveRestoreBlockHandler::RestoreGlobalEntity( CBaseEntity *pEntity, CSaveRestoreData *pSaveData, entitytable_t *pEntInfo )
  2385. {
  2386. Vector oldOffset;
  2387. EHANDLE hEntitySafeHandle;
  2388. hEntitySafeHandle = pEntity;
  2389. oldOffset.Init();
  2390. CRestore restoreHelper( pSaveData );
  2391. string_t globalName = pEntInfo->globalname, className = pEntInfo->classname;
  2392. // -------------------
  2393. int globalIndex = GlobalEntity_GetIndex( globalName );
  2394. // Don't overlay any instance of the global that isn't the latest
  2395. // pSaveData->szCurrentMapName is the level this entity is coming from
  2396. // pGlobal->levelName is the last level the global entity was active in.
  2397. // If they aren't the same, then this global update is out of date.
  2398. if ( !FStrEq( pSaveData->levelInfo.szCurrentMapName, GlobalEntity_GetMap(globalIndex) ) )
  2399. {
  2400. return 0;
  2401. }
  2402. // Compute the new global offset
  2403. CBaseEntity *pNewEntity = FindGlobalEntity( className, globalName );
  2404. if ( pNewEntity )
  2405. {
  2406. // Msg( "Overlay %s with %s\n", pNewEntity->GetClassname(), STRING(tmpEnt->classname) );
  2407. // Tell the restore code we're overlaying a global entity from another level
  2408. restoreHelper.SetGlobalMode( 1 ); // Don't overwrite global fields
  2409. pSaveData->modelSpaceOffset = pEntInfo->landmarkModelSpace - ModelSpaceLandmark( pNewEntity->GetModelIndex() );
  2410. UTIL_Remove( pEntity );
  2411. pEntity = pNewEntity;// we're going to restore this data OVER the old entity
  2412. pEntInfo->hEnt = pEntity;
  2413. // HACKHACK: Do we need system-wide support for removing non-global spawn allocated resources?
  2414. pEntity->VPhysicsDestroyObject();
  2415. Assert( pEntInfo->edictindex == -1 );
  2416. // Update the global table to say that the global definition of this entity should come from this level
  2417. GlobalEntity_SetMap( globalIndex, gpGlobals->mapname );
  2418. }
  2419. else
  2420. {
  2421. // This entity will be freed automatically by the engine-> If we don't do a restore on a matching entity (below)
  2422. // or call EntityUpdate() to move it to this level, we haven't changed global state at all.
  2423. DevMsg( "Warning: No match for global entity %s found in destination level\n", STRING(globalName) );
  2424. return 0;
  2425. }
  2426. if ( !DoRestoreEntity( pEntity, &restoreHelper ) )
  2427. {
  2428. pEntity = NULL;
  2429. }
  2430. // Is this an overriding global entity (coming over the transition)
  2431. pSaveData->modelSpaceOffset.Init();
  2432. if ( pEntity )
  2433. return 1;
  2434. return 0;
  2435. }
  2436. #endif // !defined( CLIENT_DLL )
  2437. //-----------------------------------------------------------------------------
  2438. CSaveRestoreData *SaveInit( int size )
  2439. {
  2440. CSaveRestoreData *pSaveData;
  2441. #if ( defined( CLIENT_DLL ) || defined( DISABLE_DEBUG_HISTORY ) )
  2442. if ( size <= 0 )
  2443. size = 2*1024*1024; // Reserve 2048K for now, UNDONE: Shrink this after compressing strings
  2444. #else
  2445. if ( size <= 0 )
  2446. size = 3*1024*1024; // Reserve 3096K for now, UNDONE: Shrink this after compressing strings
  2447. #endif
  2448. int numentities;
  2449. #if !defined( CLIENT_DLL )
  2450. numentities = gEntList.NumberOfEntities();
  2451. #else
  2452. numentities = ClientEntityList().NumberOfEntities();
  2453. #endif
  2454. void *pSaveMemory = engine->SaveAllocMemory( sizeof(CSaveRestoreData) + (sizeof(entitytable_t) * numentities) + size, sizeof(char) );
  2455. if ( !pSaveMemory )
  2456. {
  2457. return NULL;
  2458. }
  2459. pSaveData = MakeSaveRestoreData( pSaveMemory );
  2460. pSaveData->Init( (char *)(pSaveData + 1), size ); // skip the save structure
  2461. const int nTokens = 0xfff; // Assume a maximum of 4K-1 symbol table entries(each of some length)
  2462. pSaveMemory = engine->SaveAllocMemory( nTokens, sizeof( char * ) );
  2463. if ( !pSaveMemory )
  2464. {
  2465. engine->SaveFreeMemory( pSaveMemory );
  2466. return NULL;
  2467. }
  2468. pSaveData->InitSymbolTable( (char **)pSaveMemory, nTokens );
  2469. //---------------------------------
  2470. pSaveData->levelInfo.time = gpGlobals->curtime; // Use DLL time
  2471. pSaveData->levelInfo.vecLandmarkOffset = vec3_origin;
  2472. pSaveData->levelInfo.fUseLandmark = false;
  2473. pSaveData->levelInfo.connectionCount = 0;
  2474. //---------------------------------
  2475. gpGlobals->pSaveData = pSaveData;
  2476. return pSaveData;
  2477. }
  2478. //-----------------------------------------------------------------------------
  2479. //
  2480. // ISaveRestoreBlockSet
  2481. //
  2482. // Purpose: Serves as holder for a group of sibling save sections. Takes
  2483. // care of iterating over them, making sure read points are
  2484. // queued up to the right spot (in case one section due to datadesc
  2485. // changes reads less than expected, or doesn't leave the
  2486. // read pointer at the right point), and ensuring the read pointer
  2487. // is at the end of the entire set when the set read is done.
  2488. //-----------------------------------------------------------------------------
  2489. struct SaveRestoreBlockHeader_t
  2490. {
  2491. char szName[MAX_BLOCK_NAME_LEN + 1];
  2492. int locHeader;
  2493. int locBody;
  2494. DECLARE_SIMPLE_DATADESC();
  2495. };
  2496. //-------------------------------------
  2497. class CSaveRestoreBlockSet : public ISaveRestoreBlockSet
  2498. {
  2499. public:
  2500. CSaveRestoreBlockSet( const char *pszName )
  2501. {
  2502. Q_strncpy( m_Name, pszName, sizeof(m_Name) );
  2503. }
  2504. const char *GetBlockName()
  2505. {
  2506. return m_Name;
  2507. }
  2508. //---------------------------------
  2509. void PreSave( CSaveRestoreData *pData )
  2510. {
  2511. m_BlockHeaders.SetCount( m_Handlers.Count() );
  2512. for ( int i = 0; i < m_Handlers.Count(); i++ )
  2513. {
  2514. Q_strncpy( m_BlockHeaders[i].szName, m_Handlers[i]->GetBlockName(), MAX_BLOCK_NAME_LEN + 1 );
  2515. m_Handlers[i]->PreSave( pData );
  2516. }
  2517. }
  2518. void Save( ISave *pSave )
  2519. {
  2520. int base = pSave->GetWritePos();
  2521. for ( int i = 0; i < m_Handlers.Count(); i++ )
  2522. {
  2523. m_BlockHeaders[i].locBody = pSave->GetWritePos() - base;
  2524. m_Handlers[i]->Save( pSave );
  2525. }
  2526. m_SizeBodies = pSave->GetWritePos() - base;
  2527. }
  2528. void WriteSaveHeaders( ISave *pSave )
  2529. {
  2530. int base = pSave->GetWritePos();
  2531. //
  2532. // Reserve space for a fully populated header
  2533. //
  2534. int dummyInt = -1;
  2535. CUtlVector<SaveRestoreBlockHeader_t> dummyArr;
  2536. dummyArr.SetCount( m_BlockHeaders.Count() );
  2537. memset( &dummyArr[0], 0xff, dummyArr.Count() * sizeof(SaveRestoreBlockHeader_t) );
  2538. pSave->WriteInt( &dummyInt ); // size all headers
  2539. pSave->WriteInt( &dummyInt ); // size all bodies
  2540. SaveUtlVector( pSave, &dummyArr, FIELD_EMBEDDED );
  2541. //
  2542. // Write the data
  2543. //
  2544. for ( int i = 0; i < m_Handlers.Count(); i++ )
  2545. {
  2546. m_BlockHeaders[i].locHeader = pSave->GetWritePos() - base;
  2547. m_Handlers[i]->WriteSaveHeaders( pSave );
  2548. }
  2549. m_SizeHeaders = pSave->GetWritePos() - base;
  2550. //
  2551. // Write the actual header
  2552. //
  2553. int savedPos = pSave->GetWritePos();
  2554. pSave->SetWritePos(base);
  2555. pSave->WriteInt( &m_SizeHeaders );
  2556. pSave->WriteInt( &m_SizeBodies );
  2557. SaveUtlVector( pSave, &m_BlockHeaders, FIELD_EMBEDDED );
  2558. pSave->SetWritePos(savedPos);
  2559. }
  2560. void PostSave()
  2561. {
  2562. for ( int i = 0; i < m_Handlers.Count(); i++ )
  2563. {
  2564. m_Handlers[i]->PostSave();
  2565. }
  2566. m_BlockHeaders.Purge();
  2567. }
  2568. //---------------------------------
  2569. void PreRestore()
  2570. {
  2571. for ( int i = 0; i < m_Handlers.Count(); i++ )
  2572. {
  2573. m_Handlers[i]->PreRestore();
  2574. }
  2575. }
  2576. void ReadRestoreHeaders( IRestore *pRestore )
  2577. {
  2578. int base = pRestore->GetReadPos();
  2579. pRestore->ReadInt( &m_SizeHeaders );
  2580. pRestore->ReadInt( &m_SizeBodies );
  2581. RestoreUtlVector( pRestore, &m_BlockHeaders, FIELD_EMBEDDED );
  2582. for ( int i = 0; i < m_Handlers.Count(); i++ )
  2583. {
  2584. int location = GetBlockHeaderLoc( m_Handlers[i]->GetBlockName() );
  2585. if ( location != -1 )
  2586. {
  2587. pRestore->SetReadPos( base + location );
  2588. m_Handlers[i]->ReadRestoreHeaders( pRestore );
  2589. }
  2590. }
  2591. pRestore->SetReadPos( base + m_SizeHeaders );
  2592. }
  2593. void CallBlockHandlerRestore( ISaveRestoreBlockHandler *pHandler, int baseFilePos, IRestore *pRestore, bool fCreatePlayers )
  2594. {
  2595. int location = GetBlockBodyLoc( pHandler->GetBlockName() );
  2596. if ( location != -1 )
  2597. {
  2598. pRestore->SetReadPos( baseFilePos + location );
  2599. pHandler->Restore( pRestore, fCreatePlayers );
  2600. }
  2601. }
  2602. void Restore( IRestore *pRestore, bool fCreatePlayers )
  2603. {
  2604. int base = pRestore->GetReadPos();
  2605. for ( int i = 0; i < m_Handlers.Count(); i++ )
  2606. {
  2607. CallBlockHandlerRestore( m_Handlers[i], base, pRestore, fCreatePlayers );
  2608. }
  2609. pRestore->SetReadPos( base + m_SizeBodies );
  2610. }
  2611. void PostRestore()
  2612. {
  2613. for ( int i = 0; i < m_Handlers.Count(); i++ )
  2614. {
  2615. m_Handlers[i]->PostRestore();
  2616. }
  2617. m_BlockHeaders.Purge();
  2618. }
  2619. //---------------------------------
  2620. void AddBlockHandler( ISaveRestoreBlockHandler *pHandler )
  2621. {
  2622. // Grody, but... while this class is still isolated in saverestore.cpp, this seems like a fine time to assert:
  2623. AssertMsg( pHandler == &g_EntitySaveRestoreBlockHandler || (m_Handlers.Count() >= 1 && m_Handlers[0] == &g_EntitySaveRestoreBlockHandler), "Expected entity save load to always be first" );
  2624. Assert( pHandler != this );
  2625. m_Handlers.AddToTail( pHandler );
  2626. }
  2627. void RemoveBlockHandler( ISaveRestoreBlockHandler *pHandler )
  2628. {
  2629. m_Handlers.FindAndRemove( pHandler );
  2630. }
  2631. //---------------------------------
  2632. private:
  2633. int GetBlockBodyLoc( const char *pszName )
  2634. {
  2635. for ( int i = 0; i < m_BlockHeaders.Count(); i++ )
  2636. {
  2637. if ( strcmp( m_BlockHeaders[i].szName, pszName ) == 0 )
  2638. return m_BlockHeaders[i].locBody;
  2639. }
  2640. return -1;
  2641. }
  2642. int GetBlockHeaderLoc( const char *pszName )
  2643. {
  2644. for ( int i = 0; i < m_BlockHeaders.Count(); i++ )
  2645. {
  2646. if ( strcmp( m_BlockHeaders[i].szName, pszName ) == 0 )
  2647. return m_BlockHeaders[i].locHeader;
  2648. }
  2649. return -1;
  2650. }
  2651. char m_Name[MAX_BLOCK_NAME_LEN + 1];
  2652. CUtlVector<ISaveRestoreBlockHandler *> m_Handlers;
  2653. int m_SizeHeaders;
  2654. int m_SizeBodies;
  2655. CUtlVector<SaveRestoreBlockHeader_t> m_BlockHeaders;
  2656. };
  2657. //-------------------------------------
  2658. BEGIN_SIMPLE_DATADESC( SaveRestoreBlockHeader_t )
  2659. DEFINE_ARRAY(szName, FIELD_CHARACTER, MAX_BLOCK_NAME_LEN + 1),
  2660. DEFINE_FIELD(locHeader, FIELD_INTEGER),
  2661. DEFINE_FIELD(locBody, FIELD_INTEGER),
  2662. END_DATADESC()
  2663. //-------------------------------------
  2664. CSaveRestoreBlockSet g_SaveRestoreBlockSet("Game");
  2665. ISaveRestoreBlockSet *g_pGameSaveRestoreBlockSet = &g_SaveRestoreBlockSet;
  2666. //=============================================================================
  2667. #if !defined( CLIENT_DLL )
  2668. //------------------------------------------------------------------------------
  2669. // Creates all entities that lie in the transition list
  2670. //------------------------------------------------------------------------------
  2671. void CreateEntitiesInTransitionList( CSaveRestoreData *pSaveData, int levelMask )
  2672. {
  2673. CBaseEntity *pent;
  2674. int i;
  2675. for ( i = 0; i < pSaveData->NumEntities(); i++ )
  2676. {
  2677. entitytable_t *pEntInfo = pSaveData->GetEntityInfo( i );
  2678. pEntInfo->hEnt = NULL;
  2679. if ( pEntInfo->size == 0 || pEntInfo->edictindex == 0 )
  2680. continue;
  2681. if ( pEntInfo->classname == NULL_STRING )
  2682. {
  2683. Warning( "Entity with data saved, but with no classname\n" );
  2684. Assert(0);
  2685. continue;
  2686. }
  2687. bool active = (pEntInfo->flags & levelMask) ? 1 : 0;
  2688. // spawn players
  2689. pent = NULL;
  2690. if ( (pEntInfo->edictindex > 0) && (pEntInfo->edictindex <= gpGlobals->maxClients) )
  2691. {
  2692. edict_t *ed = INDEXENT( pEntInfo->edictindex );
  2693. if ( active && ed && !ed->IsFree() )
  2694. {
  2695. if ( !(pEntInfo->flags & FENTTABLE_PLAYER) )
  2696. {
  2697. Warning( "ENTITY IS NOT A PLAYER: %d\n" , i );
  2698. Assert(0);
  2699. }
  2700. pent = CBasePlayer::CreatePlayer( STRING(pEntInfo->classname), ed );
  2701. }
  2702. }
  2703. else if ( active )
  2704. {
  2705. pent = CreateEntityByName( STRING(pEntInfo->classname) );
  2706. }
  2707. pEntInfo->hEnt = pent;
  2708. }
  2709. }
  2710. //-----------------------------------------------------------------------------
  2711. int CreateEntityTransitionList( CSaveRestoreData *pSaveData, int levelMask )
  2712. {
  2713. CBaseEntity *pent;
  2714. entitytable_t *pEntInfo;
  2715. // Create entity list
  2716. CreateEntitiesInTransitionList( pSaveData, levelMask );
  2717. // Now spawn entities
  2718. CUtlVector<int> checkList;
  2719. int i;
  2720. int movedCount = 0;
  2721. for ( i = 0; i < pSaveData->NumEntities(); i++ )
  2722. {
  2723. pEntInfo = pSaveData->GetEntityInfo( i );
  2724. pent = pEntInfo->hEnt;
  2725. // pSaveData->currentIndex = i;
  2726. pSaveData->Seek( pEntInfo->location );
  2727. // clear this out - it must be set on a per-entity basis
  2728. pSaveData->modelSpaceOffset.Init();
  2729. if ( pent && (pEntInfo->flags & levelMask) ) // Screen out the player if he's not to be spawned
  2730. {
  2731. if ( pEntInfo->flags & FENTTABLE_GLOBAL )
  2732. {
  2733. DevMsg( 2, "Merging changes for global: %s\n", STRING(pEntInfo->classname) );
  2734. // -------------------------------------------------------------------------
  2735. // Pass the "global" flag to the DLL to indicate this entity should only override
  2736. // a matching entity, not be spawned
  2737. if ( g_EntitySaveRestoreBlockHandler.RestoreGlobalEntity( pent, pSaveData, pEntInfo ) > 0 )
  2738. {
  2739. movedCount++;
  2740. pEntInfo->restoreentityindex = pEntInfo->hEnt.Get()->entindex();
  2741. AddRestoredEntity( pEntInfo->hEnt.Get() );
  2742. }
  2743. else
  2744. {
  2745. UTIL_RemoveImmediate( pEntInfo->hEnt.Get() );
  2746. }
  2747. // -------------------------------------------------------------------------
  2748. }
  2749. else
  2750. {
  2751. DevMsg( 2, "Transferring %s (%d)\n", STRING(pEntInfo->classname), pent->edict() ? ENTINDEX(pent->edict()) : -1 );
  2752. CRestore restoreHelper( pSaveData );
  2753. if ( g_EntitySaveRestoreBlockHandler.RestoreEntity( pent, &restoreHelper, pEntInfo ) < 0 )
  2754. {
  2755. UTIL_RemoveImmediate( pent );
  2756. }
  2757. else
  2758. {
  2759. // needs to be checked. Do this in a separate pass so that pointers & hierarchy can be traversed
  2760. checkList.AddToTail(i);
  2761. }
  2762. }
  2763. // Remove any entities that were removed using UTIL_Remove() as a result of the above calls to UTIL_RemoveImmediate()
  2764. gEntList.CleanupDeleteList();
  2765. }
  2766. }
  2767. for ( i = checkList.Count()-1; i >= 0; --i )
  2768. {
  2769. pEntInfo = pSaveData->GetEntityInfo( checkList[i] );
  2770. pent = pEntInfo->hEnt;
  2771. // NOTE: pent can be NULL because UTIL_RemoveImmediate (called below) removes all in hierarchy
  2772. if ( !pent )
  2773. continue;
  2774. MDLCACHE_CRITICAL_SECTION();
  2775. if ( !(pEntInfo->flags & FENTTABLE_PLAYER) && UTIL_EntityInSolid( pent ) )
  2776. {
  2777. // this can happen during normal processing - PVS is just a guess, some map areas won't exist in the new map
  2778. DevMsg( 2, "Suppressing %s\n", STRING(pEntInfo->classname) );
  2779. UTIL_RemoveImmediate( pent );
  2780. // Remove any entities that were removed using UTIL_Remove() as a result of the above calls to UTIL_RemoveImmediate()
  2781. gEntList.CleanupDeleteList();
  2782. }
  2783. else
  2784. {
  2785. movedCount++;
  2786. pEntInfo->flags = FENTTABLE_REMOVED;
  2787. pEntInfo->restoreentityindex = pent->entindex();
  2788. AddRestoredEntity( pent );
  2789. }
  2790. }
  2791. return movedCount;
  2792. }
  2793. #endif