Counter Strike : Global Offensive Source Code
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.

3759 lines
98 KiB

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