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

1871 lines
48 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. // $NoKeywords: $
  6. //
  7. //=============================================================================//
  8. /*
  9. Entity Data Descriptions
  10. Each entity has an array which defines it's data in way that is useful for
  11. entity communication, parsing initial values from the map, and save/restore.
  12. each entity has to have the following line in it's class declaration:
  13. DECLARE_DATADESC();
  14. this line defines that it has an m_DataDesc[] array, and declares functions through
  15. which various subsystems can iterate the data.
  16. In it's implementation, each entity has to have:
  17. typedescription_t CBaseEntity::m_DataDesc[] = { ... }
  18. in which all it's data is defined (see below), followed by:
  19. which implements the functions necessary for iterating through an entities data desc.
  20. There are several types of data:
  21. FIELD : this is a variable which gets saved & loaded from disk
  22. KEY : this variable can be read in from the map file
  23. GLOBAL : a global field is actually local; it is saved/restored, but is actually
  24. unique to the entity on each level.
  25. CUSTOM : the save/restore parsing functions are described by the user.
  26. ARRAY : an array of values
  27. OUTPUT : a variable or event that can be connected to other entities (see below)
  28. INPUTFUNC : maps a string input to a function pointer. Outputs connected to this input
  29. will call the notify function when fired.
  30. INPUT : maps a string input to a member variable. Outputs connected to this input
  31. will update the input data value when fired.
  32. INPUTNOTIFY : maps a string input to a member variable/function pointer combo. Outputs
  33. connected to this input will update the data value and call the notify
  34. function when fired.
  35. some of these can overlap. all the data descriptions usable are:
  36. DEFINE_FIELD( name, fieldtype )
  37. DEFINE_KEYFIELD( name, fieldtype, mapname )
  38. DEFINE_KEYFIELD_NOTSAVED( name, fieldtype, mapname )
  39. DEFINE_ARRAY( name, fieldtype, count )
  40. DEFINE_GLOBAL_FIELD(name, fieldtype )
  41. DEFINE_CUSTOM_FIELD(name, datafuncs, mapname )
  42. DEFINE_GLOBAL_KEYFIELD(name, fieldtype, mapname )
  43. where:
  44. type is the name of the class (eg. CBaseEntity)
  45. name is the name of the variable in the class (eg. m_iHealth)
  46. fieldtype is the type of data (FIELD_STRING, FIELD_INTEGER, etc)
  47. mapname is the string by which this variable is associated with map file data
  48. count is the number of items in the array
  49. datafuncs is a struct containing function pointers for a custom-defined save/restore/parse
  50. OUTPUTS:
  51. DEFINE_OUTPUT( outputvar, outputname )
  52. This maps the string 'outputname' to the COutput-derived member variable outputvar. In the VMF
  53. file these outputs can be hooked up to inputs (see above). Whenever the internal state
  54. of an entity changes it will often fire off outputs so that map makers can hook up behaviors.
  55. e.g. A door entity would have OnDoorOpen, OnDoorClose, OnTouched, etc outputs.
  56. */
  57. #include "cbase.h"
  58. #include "entitylist.h"
  59. #include "mapentities_shared.h"
  60. #include "isaverestore.h"
  61. #include "eventqueue.h"
  62. #include "entityinput.h"
  63. #include "entityoutput.h"
  64. #include "mempool.h"
  65. #include "tier1/strtools.h"
  66. #include "datacache/imdlcache.h"
  67. #include "env_debughistory.h"
  68. #include "tier0/vprof.h"
  69. // memdbgon must be the last include file in a .cpp file!!!
  70. #include "tier0/memdbgon.h"
  71. extern ISaveRestoreOps *variantFuncs; // function pointer set for save/restoring variants
  72. BEGIN_SIMPLE_DATADESC( CEventAction )
  73. DEFINE_FIELD( m_iTarget, FIELD_STRING ),
  74. DEFINE_FIELD( m_iTargetInput, FIELD_STRING ),
  75. DEFINE_FIELD( m_iParameter, FIELD_STRING ),
  76. DEFINE_FIELD( m_flDelay, FIELD_FLOAT ),
  77. DEFINE_FIELD( m_nTimesToFire, FIELD_INTEGER ),
  78. DEFINE_FIELD( m_iIDStamp, FIELD_INTEGER ),
  79. // This is dealt with by the Restore method
  80. // DEFINE_FIELD( m_pNext, CEventAction ),
  81. END_DATADESC()
  82. // ID Stamp used to uniquely identify every output
  83. int CEventAction::s_iNextIDStamp = 0;
  84. //-----------------------------------------------------------------------------
  85. // Purpose: Creates an event action and assigns it an unique ID stamp.
  86. // Input : ActionData - the map file data block descibing the event action.
  87. //-----------------------------------------------------------------------------
  88. CEventAction::CEventAction( const char *ActionData )
  89. {
  90. m_pNext = NULL;
  91. m_iIDStamp = ++s_iNextIDStamp;
  92. m_flDelay = 0;
  93. m_iTarget = NULL_STRING;
  94. m_iParameter = NULL_STRING;
  95. m_iTargetInput = NULL_STRING;
  96. m_nTimesToFire = EVENT_FIRE_ALWAYS;
  97. if (ActionData == NULL)
  98. return;
  99. char szToken[256];
  100. //
  101. // Parse the target name.
  102. //
  103. const char *psz = nexttoken(szToken, ActionData, ',');
  104. if (szToken[0] != '\0')
  105. {
  106. m_iTarget = AllocPooledString(szToken);
  107. }
  108. //
  109. // Parse the input name.
  110. //
  111. psz = nexttoken(szToken, psz, ',');
  112. if (szToken[0] != '\0')
  113. {
  114. m_iTargetInput = AllocPooledString(szToken);
  115. }
  116. else
  117. {
  118. m_iTargetInput = AllocPooledString("Use");
  119. }
  120. //
  121. // Parse the parameter override.
  122. //
  123. psz = nexttoken(szToken, psz, ',');
  124. if (szToken[0] != '\0')
  125. {
  126. m_iParameter = AllocPooledString(szToken);
  127. }
  128. //
  129. // Parse the delay.
  130. //
  131. psz = nexttoken(szToken, psz, ',');
  132. if (szToken[0] != '\0')
  133. {
  134. m_flDelay = atof(szToken);
  135. }
  136. //
  137. // Parse the number of times to fire.
  138. //
  139. nexttoken(szToken, psz, ',');
  140. if (szToken[0] != '\0')
  141. {
  142. m_nTimesToFire = atoi(szToken);
  143. if (m_nTimesToFire == 0)
  144. {
  145. m_nTimesToFire = EVENT_FIRE_ALWAYS;
  146. }
  147. }
  148. }
  149. // this memory pool stores blocks around the size of CEventAction/inputitem_t structs
  150. // can be used for other blocks; will error if to big a block is tried to be allocated
  151. CUtlMemoryPool g_EntityListPool( MAX(sizeof(CEventAction),sizeof(CMultiInputVar::inputitem_t)), 512, CUtlMemoryPool::GROW_FAST, "g_EntityListPool" );
  152. #include "tier0/memdbgoff.h"
  153. void *CEventAction::operator new( size_t stAllocateBlock )
  154. {
  155. return g_EntityListPool.Alloc( stAllocateBlock );
  156. }
  157. void *CEventAction::operator new( size_t stAllocateBlock, int nBlockUse, const char *pFileName, int nLine )
  158. {
  159. return g_EntityListPool.Alloc( stAllocateBlock );
  160. }
  161. void CEventAction::operator delete( void *pMem )
  162. {
  163. g_EntityListPool.Free( pMem );
  164. }
  165. #include "tier0/memdbgon.h"
  166. //-----------------------------------------------------------------------------
  167. // Purpose: Returns the highest-valued delay in our list of event actions.
  168. //-----------------------------------------------------------------------------
  169. float CBaseEntityOutput::GetMaxDelay(void)
  170. {
  171. float flMaxDelay = 0;
  172. CEventAction *ev = m_ActionList;
  173. while (ev != NULL)
  174. {
  175. if (ev->m_flDelay > flMaxDelay)
  176. {
  177. flMaxDelay = ev->m_flDelay;
  178. }
  179. ev = ev->m_pNext;
  180. }
  181. return(flMaxDelay);
  182. }
  183. //-----------------------------------------------------------------------------
  184. // Purpose: Destructor.
  185. //-----------------------------------------------------------------------------
  186. CBaseEntityOutput::~CBaseEntityOutput()
  187. {
  188. CEventAction *ev = m_ActionList;
  189. while (ev != NULL)
  190. {
  191. CEventAction *pNext = ev->m_pNext;
  192. delete ev;
  193. ev = pNext;
  194. }
  195. }
  196. //-----------------------------------------------------------------------------
  197. // Purpose: Fires the event, causing a sequence of action to occur in other ents.
  198. // Input : pActivator - Entity that initiated this sequence of actions.
  199. // pCaller - Entity that is actually causing the event.
  200. //-----------------------------------------------------------------------------
  201. void CBaseEntityOutput::FireOutput(variant_t Value, CBaseEntity *pActivator, CBaseEntity *pCaller, float fDelay)
  202. {
  203. //
  204. // Iterate through all eventactions and fire them off.
  205. //
  206. CEventAction *ev = m_ActionList;
  207. CEventAction *prev = NULL;
  208. while (ev != NULL)
  209. {
  210. if (ev->m_iParameter == NULL_STRING)
  211. {
  212. //
  213. // Post the event with the default parameter.
  214. //
  215. g_EventQueue.AddEvent( STRING(ev->m_iTarget), STRING(ev->m_iTargetInput), Value, ev->m_flDelay + fDelay, pActivator, pCaller, ev->m_iIDStamp );
  216. }
  217. else
  218. {
  219. //
  220. // Post the event with a parameter override.
  221. //
  222. variant_t ValueOverride;
  223. ValueOverride.SetString( ev->m_iParameter );
  224. g_EventQueue.AddEvent( STRING(ev->m_iTarget), STRING(ev->m_iTargetInput), ValueOverride, ev->m_flDelay, pActivator, pCaller, ev->m_iIDStamp );
  225. }
  226. if ( ev->m_flDelay )
  227. {
  228. char szBuffer[256];
  229. Q_snprintf( szBuffer,
  230. sizeof(szBuffer),
  231. "(%0.2f) output: (%s,%s) -> (%s,%s,%.1f)(%s)\n",
  232. #ifdef TF_DLL
  233. engine->GetServerTime(),
  234. #else
  235. gpGlobals->curtime,
  236. #endif
  237. pCaller ? STRING(pCaller->m_iClassname) : "NULL",
  238. pCaller ? STRING(pCaller->GetEntityName()) : "NULL",
  239. STRING(ev->m_iTarget),
  240. STRING(ev->m_iTargetInput),
  241. ev->m_flDelay,
  242. STRING(ev->m_iParameter) );
  243. DevMsg( 2, "%s", szBuffer );
  244. ADD_DEBUG_HISTORY( HISTORY_ENTITY_IO, szBuffer );
  245. }
  246. else
  247. {
  248. char szBuffer[256];
  249. Q_snprintf( szBuffer,
  250. sizeof(szBuffer),
  251. "(%0.2f) output: (%s,%s) -> (%s,%s)(%s)\n",
  252. #ifdef TF_DLL
  253. engine->GetServerTime(),
  254. #else
  255. gpGlobals->curtime,
  256. #endif
  257. pCaller ? STRING(pCaller->m_iClassname) : "NULL",
  258. pCaller ? STRING(pCaller->GetEntityName()) : "NULL", STRING(ev->m_iTarget),
  259. STRING(ev->m_iTargetInput),
  260. STRING(ev->m_iParameter) );
  261. DevMsg( 2, "%s", szBuffer );
  262. ADD_DEBUG_HISTORY( HISTORY_ENTITY_IO, szBuffer );
  263. }
  264. if ( pCaller && pCaller->m_debugOverlays & OVERLAY_MESSAGE_BIT)
  265. {
  266. pCaller->DrawOutputOverlay(ev);
  267. }
  268. //
  269. // Remove the event action from the list if it was set to be fired a finite
  270. // number of times (and has been).
  271. //
  272. bool bRemove = false;
  273. if (ev->m_nTimesToFire != EVENT_FIRE_ALWAYS)
  274. {
  275. ev->m_nTimesToFire--;
  276. if (ev->m_nTimesToFire == 0)
  277. {
  278. char szBuffer[256];
  279. Q_snprintf( szBuffer, sizeof(szBuffer), "Removing from action list: (%s,%s) -> (%s,%s)\n", pCaller ? STRING(pCaller->m_iClassname) : "NULL", pCaller ? STRING(pCaller->GetEntityName()) : "NULL", STRING(ev->m_iTarget), STRING(ev->m_iTargetInput));
  280. DevMsg( 2, "%s", szBuffer );
  281. ADD_DEBUG_HISTORY( HISTORY_ENTITY_IO, szBuffer );
  282. bRemove = true;
  283. }
  284. }
  285. if (!bRemove)
  286. {
  287. prev = ev;
  288. ev = ev->m_pNext;
  289. }
  290. else
  291. {
  292. if (prev != NULL)
  293. {
  294. prev->m_pNext = ev->m_pNext;
  295. }
  296. else
  297. {
  298. m_ActionList = ev->m_pNext;
  299. }
  300. CEventAction *next = ev->m_pNext;
  301. delete ev;
  302. ev = next;
  303. }
  304. }
  305. }
  306. //-----------------------------------------------------------------------------
  307. // Purpose: Parameterless firing of an event
  308. // Input : pActivator -
  309. // pCaller -
  310. //-----------------------------------------------------------------------------
  311. void COutputEvent::FireOutput(CBaseEntity *pActivator, CBaseEntity *pCaller, float fDelay)
  312. {
  313. variant_t Val;
  314. Val.Set( FIELD_VOID, NULL );
  315. CBaseEntityOutput::FireOutput(Val, pActivator, pCaller, fDelay);
  316. }
  317. void CBaseEntityOutput::ParseEventAction( const char *EventData )
  318. {
  319. AddEventAction( new CEventAction( EventData ) );
  320. }
  321. void CBaseEntityOutput::AddEventAction( CEventAction *pEventAction )
  322. {
  323. pEventAction->m_pNext = m_ActionList;
  324. m_ActionList = pEventAction;
  325. }
  326. // save data description for the event queue
  327. BEGIN_SIMPLE_DATADESC( CBaseEntityOutput )
  328. DEFINE_CUSTOM_FIELD( m_Value, variantFuncs ),
  329. // This is saved manually by CBaseEntityOutput::Save
  330. // DEFINE_FIELD( m_ActionList, CEventAction ),
  331. END_DATADESC()
  332. int CBaseEntityOutput::Save( ISave &save )
  333. {
  334. // save that value out to disk, so we know how many to restore
  335. if ( !save.WriteFields( "Value", this, NULL, m_DataMap.dataDesc, m_DataMap.dataNumFields ) )
  336. return 0;
  337. for ( CEventAction *ev = m_ActionList; ev != NULL; ev = ev->m_pNext )
  338. {
  339. if ( !save.WriteFields( "EntityOutput", ev, NULL, ev->m_DataMap.dataDesc, ev->m_DataMap.dataNumFields ) )
  340. return 0;
  341. }
  342. return 1;
  343. }
  344. int CBaseEntityOutput::Restore( IRestore &restore, int elementCount )
  345. {
  346. // load the number of items saved
  347. if ( !restore.ReadFields( "Value", this, NULL, m_DataMap.dataDesc, m_DataMap.dataNumFields ) )
  348. return 0;
  349. m_ActionList = NULL;
  350. // read in all the fields
  351. CEventAction *lastEv = NULL;
  352. for ( int i = 0; i < elementCount; i++ )
  353. {
  354. CEventAction *ev = new CEventAction(NULL);
  355. if ( !restore.ReadFields( "EntityOutput", ev, NULL, ev->m_DataMap.dataDesc, ev->m_DataMap.dataNumFields ) )
  356. return 0;
  357. // add it to the list in the same order it was saved in
  358. if ( lastEv )
  359. {
  360. lastEv->m_pNext = ev;
  361. }
  362. else
  363. {
  364. m_ActionList = ev;
  365. }
  366. ev->m_pNext = NULL;
  367. lastEv = ev;
  368. }
  369. return 1;
  370. }
  371. int CBaseEntityOutput::NumberOfElements( void )
  372. {
  373. int count = 0;
  374. for ( CEventAction *ev = m_ActionList; ev != NULL; ev = ev->m_pNext )
  375. {
  376. count++;
  377. }
  378. return count;
  379. }
  380. /// Delete every single action in the action list.
  381. void CBaseEntityOutput::DeleteAllElements( void )
  382. {
  383. // walk front to back, deleting as we go. We needn't fix up pointers because
  384. // EVERYTHING will die.
  385. CEventAction *pNext = m_ActionList;
  386. // wipe out the head
  387. m_ActionList = NULL;
  388. while (pNext)
  389. {
  390. CEventAction *strikeThis = pNext;
  391. pNext = pNext->m_pNext;
  392. delete strikeThis;
  393. }
  394. }
  395. /// EVENTS save/restore parsing wrapper
  396. class CEventsSaveDataOps : public ISaveRestoreOps
  397. {
  398. virtual void Save( const SaveRestoreFieldInfo_t &fieldInfo, ISave *pSave )
  399. {
  400. AssertMsg( fieldInfo.pTypeDesc->fieldSize == 1, "CEventsSaveDataOps does not support arrays");
  401. CBaseEntityOutput *ev = (CBaseEntityOutput*)fieldInfo.pField;
  402. const int fieldSize = fieldInfo.pTypeDesc->fieldSize;
  403. for ( int i = 0; i < fieldSize; i++, ev++ )
  404. {
  405. // save out the number of fields
  406. int numElements = ev->NumberOfElements();
  407. pSave->WriteInt( &numElements, 1 );
  408. // save the event data
  409. ev->Save( *pSave );
  410. }
  411. }
  412. virtual void Restore( const SaveRestoreFieldInfo_t &fieldInfo, IRestore *pRestore )
  413. {
  414. AssertMsg( fieldInfo.pTypeDesc->fieldSize == 1, "CEventsSaveDataOps does not support arrays");
  415. CBaseEntityOutput *ev = (CBaseEntityOutput*)fieldInfo.pField;
  416. const int fieldSize = fieldInfo.pTypeDesc->fieldSize;
  417. for ( int i = 0; i < fieldSize; i++, ev++ )
  418. {
  419. int nElements = pRestore->ReadInt();
  420. Assert( nElements < 100 );
  421. ev->Restore( *pRestore, nElements );
  422. }
  423. }
  424. virtual bool IsEmpty( const SaveRestoreFieldInfo_t &fieldInfo )
  425. {
  426. AssertMsg( fieldInfo.pTypeDesc->fieldSize == 1, "CEventsSaveDataOps does not support arrays");
  427. // check all the elements of the array (usually only 1)
  428. CBaseEntityOutput *ev = (CBaseEntityOutput*)fieldInfo.pField;
  429. const int fieldSize = fieldInfo.pTypeDesc->fieldSize;
  430. for ( int i = 0; i < fieldSize; i++, ev++ )
  431. {
  432. // It's not empty if it has events or if it has a non-void variant value
  433. if (( ev->NumberOfElements() != 0 ) || ( ev->ValueFieldType() != FIELD_VOID ))
  434. return 0;
  435. }
  436. // variant has no data
  437. return 1;
  438. }
  439. virtual void MakeEmpty( const SaveRestoreFieldInfo_t &fieldInfo )
  440. {
  441. // Don't no how to. This is okay, since objects of this type
  442. // are always born clean before restore, and not reused
  443. }
  444. virtual bool Parse( const SaveRestoreFieldInfo_t &fieldInfo, char const* szValue )
  445. {
  446. CBaseEntityOutput *ev = (CBaseEntityOutput*)fieldInfo.pField;
  447. ev->ParseEventAction( szValue );
  448. return true;
  449. }
  450. };
  451. CEventsSaveDataOps g_EventsSaveDataOps;
  452. ISaveRestoreOps *eventFuncs = &g_EventsSaveDataOps;
  453. //-----------------------------------------------------------------------------
  454. // CMultiInputVar implementation
  455. //
  456. // Purpose: holds a list of inputs and their ID tags
  457. // used for entities that hold inputs from a set of other entities
  458. //-----------------------------------------------------------------------------
  459. //-----------------------------------------------------------------------------
  460. // Purpose: destructor, frees the data list
  461. //-----------------------------------------------------------------------------
  462. CMultiInputVar::~CMultiInputVar()
  463. {
  464. if ( m_InputList )
  465. {
  466. while ( m_InputList->next != NULL )
  467. {
  468. inputitem_t *input = m_InputList->next;
  469. m_InputList->next = input->next;
  470. delete input;
  471. }
  472. delete m_InputList;
  473. }
  474. }
  475. //-----------------------------------------------------------------------------
  476. // Purpose: Updates the data set with a new value
  477. // Input : newVal - the new value to add to or update in the list
  478. // outputID - the source of the value
  479. //-----------------------------------------------------------------------------
  480. void CMultiInputVar::AddValue( variant_t newVal, int outputID )
  481. {
  482. // see if it's already in the list
  483. inputitem_t *inp;
  484. for ( inp = m_InputList; inp != NULL; inp = inp->next )
  485. {
  486. // already in list, so just update this link
  487. if ( inp->outputID == outputID )
  488. {
  489. inp->value = newVal;
  490. return;
  491. }
  492. }
  493. // add to start of list
  494. inp = new inputitem_t;
  495. inp->value = newVal;
  496. inp->outputID = outputID;
  497. if ( !m_InputList )
  498. {
  499. m_InputList = inp;
  500. inp->next = NULL;
  501. }
  502. else
  503. {
  504. inp->next = m_InputList;
  505. m_InputList = inp;
  506. }
  507. }
  508. #include "tier0/memdbgoff.h"
  509. //-----------------------------------------------------------------------------
  510. // Purpose: allocates memory from the entitylist pool
  511. //-----------------------------------------------------------------------------
  512. void *CMultiInputVar::inputitem_t::operator new( size_t stAllocateBlock )
  513. {
  514. return g_EntityListPool.Alloc( stAllocateBlock );
  515. }
  516. void *CMultiInputVar::inputitem_t::operator new( size_t stAllocateBlock, int nBlockUse, const char *pFileName, int nLine )
  517. {
  518. return g_EntityListPool.Alloc( stAllocateBlock );
  519. }
  520. //-----------------------------------------------------------------------------
  521. // Purpose: frees memory from the entitylist pool
  522. //-----------------------------------------------------------------------------
  523. void CMultiInputVar::inputitem_t::operator delete( void *pMem )
  524. {
  525. g_EntityListPool.Free( pMem );
  526. }
  527. #include "tier0/memdbgon.h"
  528. //-----------------------------------------------------------------------------
  529. // CEventQueue implementation
  530. //
  531. // Purpose: holds and executes a global prioritized queue of entity actions
  532. //-----------------------------------------------------------------------------
  533. DEFINE_FIXEDSIZE_ALLOCATOR( EventQueuePrioritizedEvent_t, 128, CUtlMemoryPool::GROW_SLOW );
  534. CEventQueue g_EventQueue;
  535. CEventQueue::CEventQueue()
  536. {
  537. m_Events.m_flFireTime = -FLT_MAX;
  538. m_Events.m_pNext = NULL;
  539. Init();
  540. }
  541. CEventQueue::~CEventQueue()
  542. {
  543. Clear();
  544. }
  545. // Robin: Left here for backwards compatability.
  546. class CEventQueueSaveLoadProxy : public CLogicalEntity
  547. {
  548. DECLARE_CLASS( CEventQueueSaveLoadProxy, CLogicalEntity );
  549. int Save( ISave &save )
  550. {
  551. if ( !BaseClass::Save(save) )
  552. return 0;
  553. // save out the message queue
  554. return g_EventQueue.Save( save );
  555. }
  556. int Restore( IRestore &restore )
  557. {
  558. if ( !BaseClass::Restore(restore) )
  559. return 0;
  560. // restore the event queue
  561. int iReturn = g_EventQueue.Restore( restore );
  562. // Now remove myself, because the CEventQueue_SaveRestoreBlockHandler
  563. // will handle future saves.
  564. UTIL_Remove( this );
  565. return iReturn;
  566. }
  567. };
  568. LINK_ENTITY_TO_CLASS(event_queue_saveload_proxy, CEventQueueSaveLoadProxy);
  569. //-----------------------------------------------------------------------------
  570. // EVENT QUEUE SAVE / RESTORE
  571. //-----------------------------------------------------------------------------
  572. static short EVENTQUEUE_SAVE_RESTORE_VERSION = 1;
  573. class CEventQueue_SaveRestoreBlockHandler : public CDefSaveRestoreBlockHandler
  574. {
  575. public:
  576. const char *GetBlockName()
  577. {
  578. return "EventQueue";
  579. }
  580. //---------------------------------
  581. void Save( ISave *pSave )
  582. {
  583. g_EventQueue.Save( *pSave );
  584. }
  585. //---------------------------------
  586. void WriteSaveHeaders( ISave *pSave )
  587. {
  588. pSave->WriteShort( &EVENTQUEUE_SAVE_RESTORE_VERSION );
  589. }
  590. //---------------------------------
  591. void ReadRestoreHeaders( IRestore *pRestore )
  592. {
  593. // No reason why any future version shouldn't try to retain backward compatability. The default here is to not do so.
  594. short version;
  595. pRestore->ReadShort( &version );
  596. m_fDoLoad = ( version == EVENTQUEUE_SAVE_RESTORE_VERSION );
  597. }
  598. //---------------------------------
  599. void Restore( IRestore *pRestore, bool createPlayers )
  600. {
  601. if ( m_fDoLoad )
  602. {
  603. g_EventQueue.Restore( *pRestore );
  604. }
  605. }
  606. private:
  607. bool m_fDoLoad;
  608. };
  609. //-----------------------------------------------------------------------------
  610. CEventQueue_SaveRestoreBlockHandler g_EventQueue_SaveRestoreBlockHandler;
  611. //-------------------------------------
  612. ISaveRestoreBlockHandler *GetEventQueueSaveRestoreBlockHandler()
  613. {
  614. return &g_EventQueue_SaveRestoreBlockHandler;
  615. }
  616. void CEventQueue::Init( void )
  617. {
  618. Clear();
  619. }
  620. void CEventQueue::Clear( void )
  621. {
  622. // delete all the events in the queue
  623. EventQueuePrioritizedEvent_t *pe = m_Events.m_pNext;
  624. while ( pe != NULL )
  625. {
  626. EventQueuePrioritizedEvent_t *next = pe->m_pNext;
  627. delete pe;
  628. pe = next;
  629. }
  630. m_Events.m_pNext = NULL;
  631. }
  632. void CEventQueue::Dump( void )
  633. {
  634. EventQueuePrioritizedEvent_t *pe = m_Events.m_pNext;
  635. Msg("Dumping event queue. Current time is: %.2f\n",
  636. #ifdef TF_DLL
  637. engine->GetServerTime()
  638. #else
  639. gpGlobals->curtime
  640. #endif
  641. );
  642. while ( pe != NULL )
  643. {
  644. EventQueuePrioritizedEvent_t *next = pe->m_pNext;
  645. Msg(" (%.2f) Target: '%s', Input: '%s', Parameter '%s'. Activator: '%s', Caller '%s'. \n",
  646. pe->m_flFireTime,
  647. STRING(pe->m_iTarget),
  648. STRING(pe->m_iTargetInput),
  649. pe->m_VariantValue.String(),
  650. pe->m_pActivator ? pe->m_pActivator->GetDebugName() : "None",
  651. pe->m_pCaller ? pe->m_pCaller->GetDebugName() : "None" );
  652. pe = next;
  653. }
  654. Msg("Finished dump.\n");
  655. }
  656. //-----------------------------------------------------------------------------
  657. // Purpose: adds the action into the correct spot in the priority queue, targeting entity via string name
  658. //-----------------------------------------------------------------------------
  659. void CEventQueue::AddEvent( const char *target, const char *targetInput, variant_t Value, float fireDelay, CBaseEntity *pActivator, CBaseEntity *pCaller, int outputID )
  660. {
  661. // build the new event
  662. EventQueuePrioritizedEvent_t *newEvent = new EventQueuePrioritizedEvent_t;
  663. #ifdef TF_DLL
  664. newEvent->m_flFireTime = engine->GetServerTime() + fireDelay; // priority key in the priority queue
  665. #else
  666. newEvent->m_flFireTime = gpGlobals->curtime + fireDelay; // priority key in the priority queue
  667. #endif
  668. newEvent->m_iTarget = MAKE_STRING( target );
  669. newEvent->m_pEntTarget = NULL;
  670. newEvent->m_iTargetInput = MAKE_STRING( targetInput );
  671. newEvent->m_pActivator = pActivator;
  672. newEvent->m_pCaller = pCaller;
  673. newEvent->m_VariantValue = Value;
  674. newEvent->m_iOutputID = outputID;
  675. AddEvent( newEvent );
  676. }
  677. //-----------------------------------------------------------------------------
  678. // Purpose: adds the action into the correct spot in the priority queue, targeting entity via pointer
  679. //-----------------------------------------------------------------------------
  680. void CEventQueue::AddEvent( CBaseEntity *target, const char *targetInput, variant_t Value, float fireDelay, CBaseEntity *pActivator, CBaseEntity *pCaller, int outputID )
  681. {
  682. // build the new event
  683. EventQueuePrioritizedEvent_t *newEvent = new EventQueuePrioritizedEvent_t;
  684. #ifdef TF_DLL
  685. newEvent->m_flFireTime = engine->GetServerTime() + fireDelay; // primary priority key in the priority queue
  686. #else
  687. newEvent->m_flFireTime = gpGlobals->curtime + fireDelay; // primary priority key in the priority queue
  688. #endif
  689. newEvent->m_iTarget = NULL_STRING;
  690. newEvent->m_pEntTarget = target;
  691. newEvent->m_iTargetInput = MAKE_STRING( targetInput );
  692. newEvent->m_pActivator = pActivator;
  693. newEvent->m_pCaller = pCaller;
  694. newEvent->m_VariantValue = Value;
  695. newEvent->m_iOutputID = outputID;
  696. AddEvent( newEvent );
  697. }
  698. void CEventQueue::AddEvent( CBaseEntity *target, const char *action, float fireDelay, CBaseEntity *pActivator, CBaseEntity *pCaller, int outputID )
  699. {
  700. variant_t Value;
  701. Value.Set( FIELD_VOID, NULL );
  702. AddEvent( target, action, Value, fireDelay, pActivator, pCaller, outputID );
  703. }
  704. //-----------------------------------------------------------------------------
  705. // Purpose: private function, adds an event into the list
  706. // Input : *newEvent - the (already built) event to add
  707. //-----------------------------------------------------------------------------
  708. void CEventQueue::AddEvent( EventQueuePrioritizedEvent_t *newEvent )
  709. {
  710. // loop through the actions looking for a place to insert
  711. EventQueuePrioritizedEvent_t *pe;
  712. for ( pe = &m_Events; pe->m_pNext != NULL; pe = pe->m_pNext )
  713. {
  714. if ( pe->m_pNext->m_flFireTime > newEvent->m_flFireTime )
  715. {
  716. break;
  717. }
  718. }
  719. Assert( pe );
  720. // insert
  721. newEvent->m_pNext = pe->m_pNext;
  722. newEvent->m_pPrev = pe;
  723. pe->m_pNext = newEvent;
  724. if ( newEvent->m_pNext )
  725. {
  726. newEvent->m_pNext->m_pPrev = newEvent;
  727. }
  728. }
  729. void CEventQueue::RemoveEvent( EventQueuePrioritizedEvent_t *pe )
  730. {
  731. Assert( pe->m_pPrev );
  732. pe->m_pPrev->m_pNext = pe->m_pNext;
  733. if ( pe->m_pNext )
  734. {
  735. pe->m_pNext->m_pPrev = pe->m_pPrev;
  736. }
  737. }
  738. //-----------------------------------------------------------------------------
  739. // Purpose: fires off any events in the queue who's fire time is (or before) the present time
  740. //-----------------------------------------------------------------------------
  741. void CEventQueue::ServiceEvents( void )
  742. {
  743. if (!CBaseEntity::Debug_ShouldStep())
  744. {
  745. return;
  746. }
  747. EventQueuePrioritizedEvent_t *pe = m_Events.m_pNext;
  748. #ifdef TF_DLL
  749. while ( pe != NULL && pe->m_flFireTime <= engine->GetServerTime() )
  750. #else
  751. while ( pe != NULL && pe->m_flFireTime <= gpGlobals->curtime )
  752. #endif
  753. {
  754. MDLCACHE_CRITICAL_SECTION();
  755. bool targetFound = false;
  756. // find the targets
  757. if ( pe->m_iTarget != NULL_STRING )
  758. {
  759. // In the context the event, the searching entity is also the caller
  760. CBaseEntity *pSearchingEntity = pe->m_pCaller;
  761. CBaseEntity *target = NULL;
  762. while ( 1 )
  763. {
  764. target = gEntList.FindEntityByName( target, pe->m_iTarget, pSearchingEntity, pe->m_pActivator, pe->m_pCaller );
  765. if ( !target )
  766. break;
  767. // pump the action into the target
  768. target->AcceptInput( STRING(pe->m_iTargetInput), pe->m_pActivator, pe->m_pCaller, pe->m_VariantValue, pe->m_iOutputID );
  769. targetFound = true;
  770. }
  771. }
  772. // direct pointer
  773. if ( pe->m_pEntTarget != NULL )
  774. {
  775. pe->m_pEntTarget->AcceptInput( STRING(pe->m_iTargetInput), pe->m_pActivator, pe->m_pCaller, pe->m_VariantValue, pe->m_iOutputID );
  776. targetFound = true;
  777. }
  778. if ( !targetFound )
  779. {
  780. // See if we can find a target if we treat the target as a classname
  781. if ( pe->m_iTarget != NULL_STRING )
  782. {
  783. CBaseEntity *target = NULL;
  784. while ( 1 )
  785. {
  786. target = gEntList.FindEntityByClassname( target, STRING(pe->m_iTarget) );
  787. if ( !target )
  788. break;
  789. // pump the action into the target
  790. target->AcceptInput( STRING(pe->m_iTargetInput), pe->m_pActivator, pe->m_pCaller, pe->m_VariantValue, pe->m_iOutputID );
  791. targetFound = true;
  792. }
  793. }
  794. }
  795. if ( !targetFound )
  796. {
  797. const char *pClass ="", *pName = "";
  798. // might be NULL
  799. if ( pe->m_pCaller )
  800. {
  801. pClass = STRING(pe->m_pCaller->m_iClassname);
  802. pName = STRING(pe->m_pCaller->GetEntityName());
  803. }
  804. char szBuffer[256];
  805. Q_snprintf( szBuffer, sizeof(szBuffer), "unhandled input: (%s) -> (%s), from (%s,%s); target entity not found\n", STRING(pe->m_iTargetInput), STRING(pe->m_iTarget), pClass, pName );
  806. DevMsg( 2, "%s", szBuffer );
  807. ADD_DEBUG_HISTORY( HISTORY_ENTITY_IO, szBuffer );
  808. }
  809. // remove the event from the list (remembering that the queue may have been added to)
  810. RemoveEvent( pe );
  811. delete pe;
  812. //
  813. // If we are in debug mode, exit the loop if we have fired the correct number of events.
  814. //
  815. if (CBaseEntity::Debug_IsPaused())
  816. {
  817. if (!CBaseEntity::Debug_Step())
  818. {
  819. break;
  820. }
  821. }
  822. // restart the list (to catch any new items have probably been added to the queue)
  823. pe = m_Events.m_pNext;
  824. }
  825. }
  826. //-----------------------------------------------------------------------------
  827. // Purpose: Dumps the contents of the Entity I/O event queue to the console.
  828. //-----------------------------------------------------------------------------
  829. void CC_DumpEventQueue()
  830. {
  831. if ( !UTIL_IsCommandIssuedByServerAdmin() )
  832. return;
  833. g_EventQueue.Dump();
  834. }
  835. static ConCommand dumpeventqueue( "dumpeventqueue", CC_DumpEventQueue, "Dump the contents of the Entity I/O event queue to the console." );
  836. //-----------------------------------------------------------------------------
  837. // Purpose: Removes all pending events from the I/O queue that were added by the
  838. // given caller.
  839. //
  840. // TODO: This is only as reliable as callers are in passing the correct
  841. // caller pointer when they fire the outputs. Make more foolproof.
  842. //-----------------------------------------------------------------------------
  843. void CEventQueue::CancelEvents( CBaseEntity *pCaller )
  844. {
  845. if (!pCaller)
  846. return;
  847. EventQueuePrioritizedEvent_t *pCur = m_Events.m_pNext;
  848. while (pCur != NULL)
  849. {
  850. bool bDelete = false;
  851. if (pCur->m_pCaller == pCaller)
  852. {
  853. // Pointers match; make sure everything else matches.
  854. if (!stricmp(STRING(pCur->m_pCaller->GetEntityName()), STRING(pCaller->GetEntityName())) &&
  855. !stricmp(pCur->m_pCaller->GetClassname(), pCaller->GetClassname()))
  856. {
  857. // Found a matching event; delete it from the queue.
  858. bDelete = true;
  859. }
  860. }
  861. EventQueuePrioritizedEvent_t *pCurSave = pCur;
  862. pCur = pCur->m_pNext;
  863. if (bDelete)
  864. {
  865. RemoveEvent( pCurSave );
  866. delete pCurSave;
  867. }
  868. }
  869. }
  870. //-----------------------------------------------------------------------------
  871. // Purpose: Removes all pending events of the specified type from the I/O queue of the specified target
  872. //
  873. // TODO: This is only as reliable as callers are in passing the correct
  874. // caller pointer when they fire the outputs. Make more foolproof.
  875. //-----------------------------------------------------------------------------
  876. void CEventQueue::CancelEventOn( CBaseEntity *pTarget, const char *sInputName )
  877. {
  878. if (!pTarget)
  879. return;
  880. EventQueuePrioritizedEvent_t *pCur = m_Events.m_pNext;
  881. while (pCur != NULL)
  882. {
  883. bool bDelete = false;
  884. if (pCur->m_pEntTarget == pTarget)
  885. {
  886. if ( !Q_strncmp( STRING(pCur->m_iTargetInput), sInputName, strlen(sInputName) ) )
  887. {
  888. // Found a matching event; delete it from the queue.
  889. bDelete = true;
  890. }
  891. }
  892. EventQueuePrioritizedEvent_t *pCurSave = pCur;
  893. pCur = pCur->m_pNext;
  894. if (bDelete)
  895. {
  896. RemoveEvent( pCurSave );
  897. delete pCurSave;
  898. }
  899. }
  900. }
  901. //-----------------------------------------------------------------------------
  902. // Purpose: Return true if the target has any pending inputs.
  903. // Input : *pTarget -
  904. // *sInputName - NULL for any input, or a specified one
  905. //-----------------------------------------------------------------------------
  906. bool CEventQueue::HasEventPending( CBaseEntity *pTarget, const char *sInputName )
  907. {
  908. if (!pTarget)
  909. return false;
  910. EventQueuePrioritizedEvent_t *pCur = m_Events.m_pNext;
  911. while (pCur != NULL)
  912. {
  913. if (pCur->m_pEntTarget == pTarget)
  914. {
  915. if ( !sInputName )
  916. return true;
  917. if ( !Q_strncmp( STRING(pCur->m_iTargetInput), sInputName, strlen(sInputName) ) )
  918. return true;
  919. }
  920. pCur = pCur->m_pNext;
  921. }
  922. return false;
  923. }
  924. void ServiceEventQueue( void )
  925. {
  926. VPROF("ServiceEventQueue()");
  927. g_EventQueue.ServiceEvents();
  928. }
  929. // save data description for the event queue
  930. BEGIN_SIMPLE_DATADESC( CEventQueue )
  931. // These are saved explicitly in CEventQueue::Save below
  932. // DEFINE_FIELD( m_Events, EventQueuePrioritizedEvent_t ),
  933. DEFINE_FIELD( m_iListCount, FIELD_INTEGER ), // this value is only used during save/restore
  934. END_DATADESC()
  935. // save data for a single event in the queue
  936. BEGIN_SIMPLE_DATADESC( EventQueuePrioritizedEvent_t )
  937. DEFINE_FIELD( m_flFireTime, FIELD_TIME ),
  938. DEFINE_FIELD( m_iTarget, FIELD_STRING ),
  939. DEFINE_FIELD( m_iTargetInput, FIELD_STRING ),
  940. DEFINE_FIELD( m_pActivator, FIELD_EHANDLE ),
  941. DEFINE_FIELD( m_pCaller, FIELD_EHANDLE ),
  942. DEFINE_FIELD( m_pEntTarget, FIELD_EHANDLE ),
  943. DEFINE_FIELD( m_iOutputID, FIELD_INTEGER ),
  944. DEFINE_CUSTOM_FIELD( m_VariantValue, variantFuncs ),
  945. // DEFINE_FIELD( m_pNext, FIELD_??? ),
  946. // DEFINE_FIELD( m_pPrev, FIELD_??? ),
  947. END_DATADESC()
  948. int CEventQueue::Save( ISave &save )
  949. {
  950. // count the number of items in the queue
  951. EventQueuePrioritizedEvent_t *pe;
  952. m_iListCount = 0;
  953. for ( pe = m_Events.m_pNext; pe != NULL; pe = pe->m_pNext )
  954. {
  955. m_iListCount++;
  956. }
  957. // save that value out to disk, so we know how many to restore
  958. if ( !save.WriteFields( "EventQueue", this, NULL, m_DataMap.dataDesc, m_DataMap.dataNumFields ) )
  959. return 0;
  960. // cycle through all the events, saving them all
  961. for ( pe = m_Events.m_pNext; pe != NULL; pe = pe->m_pNext )
  962. {
  963. if ( !save.WriteFields( "PEvent", pe, NULL, pe->m_DataMap.dataDesc, pe->m_DataMap.dataNumFields ) )
  964. return 0;
  965. }
  966. return 1;
  967. }
  968. int CEventQueue::Restore( IRestore &restore )
  969. {
  970. // clear the event queue
  971. Clear();
  972. // rebuild the event queue by restoring all the queue items
  973. EventQueuePrioritizedEvent_t tmpEvent;
  974. // load the number of items saved
  975. if ( !restore.ReadFields( "EventQueue", this, NULL, m_DataMap.dataDesc, m_DataMap.dataNumFields ) )
  976. return 0;
  977. for ( int i = 0; i < m_iListCount; i++ )
  978. {
  979. if ( !restore.ReadFields( "PEvent", &tmpEvent, NULL, tmpEvent.m_DataMap.dataDesc, tmpEvent.m_DataMap.dataNumFields ) )
  980. return 0;
  981. // add the restored event into the list
  982. if ( tmpEvent.m_pEntTarget )
  983. {
  984. AddEvent( tmpEvent.m_pEntTarget,
  985. STRING(tmpEvent.m_iTargetInput),
  986. tmpEvent.m_VariantValue,
  987. #ifdef TF_DLL
  988. tmpEvent.m_flFireTime - engine->GetServerTime(),
  989. #else
  990. tmpEvent.m_flFireTime - gpGlobals->curtime,
  991. #endif
  992. tmpEvent.m_pActivator,
  993. tmpEvent.m_pCaller,
  994. tmpEvent.m_iOutputID );
  995. }
  996. else
  997. {
  998. AddEvent( STRING(tmpEvent.m_iTarget),
  999. STRING(tmpEvent.m_iTargetInput),
  1000. tmpEvent.m_VariantValue,
  1001. #ifdef TF_DLL
  1002. tmpEvent.m_flFireTime - engine->GetServerTime(),
  1003. #else
  1004. tmpEvent.m_flFireTime - gpGlobals->curtime,
  1005. #endif
  1006. tmpEvent.m_pActivator,
  1007. tmpEvent.m_pCaller,
  1008. tmpEvent.m_iOutputID );
  1009. }
  1010. }
  1011. return 1;
  1012. }
  1013. ////////////////////////// variant_t implementation //////////////////////////
  1014. // BUGBUG: Add support for function pointer save/restore to variants
  1015. // BUGBUG: Must pass datamap_t to read/write fields
  1016. void variant_t::Set( fieldtype_t ftype, void *data )
  1017. {
  1018. fieldType = ftype;
  1019. switch ( ftype )
  1020. {
  1021. case FIELD_BOOLEAN: bVal = *((bool *)data); break;
  1022. case FIELD_CHARACTER: iVal = *((char *)data); break;
  1023. case FIELD_SHORT: iVal = *((short *)data); break;
  1024. case FIELD_INTEGER: iVal = *((int *)data); break;
  1025. case FIELD_STRING: iszVal = *((string_t *)data); break;
  1026. case FIELD_FLOAT: flVal = *((float *)data); break;
  1027. case FIELD_COLOR32: rgbaVal = *((color32 *)data); break;
  1028. case FIELD_VECTOR:
  1029. case FIELD_POSITION_VECTOR:
  1030. {
  1031. vecVal[0] = ((float *)data)[0];
  1032. vecVal[1] = ((float *)data)[1];
  1033. vecVal[2] = ((float *)data)[2];
  1034. break;
  1035. }
  1036. case FIELD_EHANDLE: eVal = *((EHANDLE *)data); break;
  1037. case FIELD_CLASSPTR: eVal = *((CBaseEntity **)data); break;
  1038. case FIELD_VOID:
  1039. default:
  1040. iVal = 0; fieldType = FIELD_VOID;
  1041. break;
  1042. }
  1043. }
  1044. //-----------------------------------------------------------------------------
  1045. // Purpose: Copies the value in the variant into a block of memory
  1046. // Input : *data - the block to write into
  1047. //-----------------------------------------------------------------------------
  1048. void variant_t::SetOther( void *data )
  1049. {
  1050. switch ( fieldType )
  1051. {
  1052. case FIELD_BOOLEAN: *((bool *)data) = bVal != 0; break;
  1053. case FIELD_CHARACTER: *((char *)data) = iVal; break;
  1054. case FIELD_SHORT: *((short *)data) = iVal; break;
  1055. case FIELD_INTEGER: *((int *)data) = iVal; break;
  1056. case FIELD_STRING: *((string_t *)data) = iszVal; break;
  1057. case FIELD_FLOAT: *((float *)data) = flVal; break;
  1058. case FIELD_COLOR32: *((color32 *)data) = rgbaVal; break;
  1059. case FIELD_VECTOR:
  1060. case FIELD_POSITION_VECTOR:
  1061. {
  1062. ((float *)data)[0] = vecVal[0];
  1063. ((float *)data)[1] = vecVal[1];
  1064. ((float *)data)[2] = vecVal[2];
  1065. break;
  1066. }
  1067. case FIELD_EHANDLE: *((EHANDLE *)data) = eVal; break;
  1068. case FIELD_CLASSPTR: *((CBaseEntity **)data) = eVal; break;
  1069. }
  1070. }
  1071. //-----------------------------------------------------------------------------
  1072. // Purpose: Converts the variant to a new type. This function defines which I/O
  1073. // types can be automatically converted between. Connections that require
  1074. // an unsupported conversion will cause an error message at runtime.
  1075. // Input : newType - the type to convert to
  1076. // Output : Returns true on success, false if the conversion is not legal
  1077. //-----------------------------------------------------------------------------
  1078. bool variant_t::Convert( fieldtype_t newType )
  1079. {
  1080. if ( newType == fieldType )
  1081. {
  1082. return true;
  1083. }
  1084. //
  1085. // Converting to a null value is easy.
  1086. //
  1087. if ( newType == FIELD_VOID )
  1088. {
  1089. Set( FIELD_VOID, NULL );
  1090. return true;
  1091. }
  1092. //
  1093. // FIELD_INPUT accepts the variant type directly.
  1094. //
  1095. if ( newType == FIELD_INPUT )
  1096. {
  1097. return true;
  1098. }
  1099. switch ( fieldType )
  1100. {
  1101. case FIELD_INTEGER:
  1102. {
  1103. switch ( newType )
  1104. {
  1105. case FIELD_FLOAT:
  1106. {
  1107. SetFloat( (float) iVal );
  1108. return true;
  1109. }
  1110. case FIELD_BOOLEAN:
  1111. {
  1112. SetBool( iVal != 0 );
  1113. return true;
  1114. }
  1115. }
  1116. break;
  1117. }
  1118. case FIELD_FLOAT:
  1119. {
  1120. switch ( newType )
  1121. {
  1122. case FIELD_INTEGER:
  1123. {
  1124. SetInt( (int) flVal );
  1125. return true;
  1126. }
  1127. case FIELD_BOOLEAN:
  1128. {
  1129. SetBool( flVal != 0 );
  1130. return true;
  1131. }
  1132. }
  1133. break;
  1134. }
  1135. //
  1136. // Everyone must convert from FIELD_STRING if possible, since
  1137. // parameter overrides are always passed as strings.
  1138. //
  1139. case FIELD_STRING:
  1140. {
  1141. switch ( newType )
  1142. {
  1143. case FIELD_INTEGER:
  1144. {
  1145. if (iszVal != NULL_STRING)
  1146. {
  1147. SetInt(atoi(STRING(iszVal)));
  1148. }
  1149. else
  1150. {
  1151. SetInt(0);
  1152. }
  1153. return true;
  1154. }
  1155. case FIELD_FLOAT:
  1156. {
  1157. if (iszVal != NULL_STRING)
  1158. {
  1159. SetFloat(atof(STRING(iszVal)));
  1160. }
  1161. else
  1162. {
  1163. SetFloat(0);
  1164. }
  1165. return true;
  1166. }
  1167. case FIELD_BOOLEAN:
  1168. {
  1169. if (iszVal != NULL_STRING)
  1170. {
  1171. SetBool( atoi(STRING(iszVal)) != 0 );
  1172. }
  1173. else
  1174. {
  1175. SetBool(false);
  1176. }
  1177. return true;
  1178. }
  1179. case FIELD_VECTOR:
  1180. {
  1181. Vector tmpVec = vec3_origin;
  1182. if (sscanf(STRING(iszVal), "[%f %f %f]", &tmpVec[0], &tmpVec[1], &tmpVec[2]) == 0)
  1183. {
  1184. // Try sucking out 3 floats with no []s
  1185. sscanf(STRING(iszVal), "%f %f %f", &tmpVec[0], &tmpVec[1], &tmpVec[2]);
  1186. }
  1187. SetVector3D( tmpVec );
  1188. return true;
  1189. }
  1190. case FIELD_COLOR32:
  1191. {
  1192. int nRed = 0;
  1193. int nGreen = 0;
  1194. int nBlue = 0;
  1195. int nAlpha = 255;
  1196. sscanf(STRING(iszVal), "%d %d %d %d", &nRed, &nGreen, &nBlue, &nAlpha);
  1197. SetColor32( nRed, nGreen, nBlue, nAlpha );
  1198. return true;
  1199. }
  1200. case FIELD_EHANDLE:
  1201. {
  1202. // convert the string to an entity by locating it by classname
  1203. CBaseEntity *ent = NULL;
  1204. if ( iszVal != NULL_STRING )
  1205. {
  1206. // FIXME: do we need to pass an activator in here?
  1207. ent = gEntList.FindEntityByName( NULL, iszVal );
  1208. }
  1209. SetEntity( ent );
  1210. return true;
  1211. }
  1212. }
  1213. break;
  1214. }
  1215. case FIELD_EHANDLE:
  1216. {
  1217. switch ( newType )
  1218. {
  1219. case FIELD_STRING:
  1220. {
  1221. // take the entities targetname as the string
  1222. string_t iszStr = NULL_STRING;
  1223. if ( eVal != NULL )
  1224. {
  1225. SetString( eVal->GetEntityName() );
  1226. }
  1227. return true;
  1228. }
  1229. }
  1230. break;
  1231. }
  1232. }
  1233. // invalid conversion
  1234. return false;
  1235. }
  1236. //-----------------------------------------------------------------------------
  1237. // Purpose: All types must be able to display as strings for debugging purposes.
  1238. // Output : Returns a pointer to the string that represents this value.
  1239. //
  1240. // NOTE: The returned pointer should not be stored by the caller as
  1241. // subsequent calls to this function will overwrite the contents
  1242. // of the buffer!
  1243. //-----------------------------------------------------------------------------
  1244. const char *variant_t::ToString( void ) const
  1245. {
  1246. COMPILE_TIME_ASSERT( sizeof(string_t) == sizeof(int) );
  1247. static char szBuf[512];
  1248. switch (fieldType)
  1249. {
  1250. case FIELD_STRING:
  1251. {
  1252. return(STRING(iszVal));
  1253. }
  1254. case FIELD_BOOLEAN:
  1255. {
  1256. if (bVal == 0)
  1257. {
  1258. Q_strncpy(szBuf, "false",sizeof(szBuf));
  1259. }
  1260. else
  1261. {
  1262. Q_strncpy(szBuf, "true",sizeof(szBuf));
  1263. }
  1264. return(szBuf);
  1265. }
  1266. case FIELD_INTEGER:
  1267. {
  1268. Q_snprintf( szBuf, sizeof( szBuf ), "%i", iVal );
  1269. return(szBuf);
  1270. }
  1271. case FIELD_FLOAT:
  1272. {
  1273. Q_snprintf(szBuf,sizeof(szBuf), "%g", flVal);
  1274. return(szBuf);
  1275. }
  1276. case FIELD_COLOR32:
  1277. {
  1278. Q_snprintf(szBuf,sizeof(szBuf), "%d %d %d %d", (int)rgbaVal.r, (int)rgbaVal.g, (int)rgbaVal.b, (int)rgbaVal.a);
  1279. return(szBuf);
  1280. }
  1281. case FIELD_VECTOR:
  1282. {
  1283. Q_snprintf(szBuf,sizeof(szBuf), "[%g %g %g]", (double)vecVal[0], (double)vecVal[1], (double)vecVal[2]);
  1284. return(szBuf);
  1285. }
  1286. case FIELD_VOID:
  1287. {
  1288. szBuf[0] = '\0';
  1289. return(szBuf);
  1290. }
  1291. case FIELD_EHANDLE:
  1292. {
  1293. const char *pszName = (Entity()) ? STRING(Entity()->GetEntityName()) : "<<null entity>>";
  1294. Q_strncpy( szBuf, pszName, 512 );
  1295. return (szBuf);
  1296. }
  1297. }
  1298. return("No conversion to string");
  1299. }
  1300. #define classNameTypedef variant_t // to satisfy DEFINE... macros
  1301. typedescription_t variant_t::m_SaveBool[] =
  1302. {
  1303. DEFINE_FIELD( bVal, FIELD_BOOLEAN ),
  1304. };
  1305. typedescription_t variant_t::m_SaveInt[] =
  1306. {
  1307. DEFINE_FIELD( iVal, FIELD_INTEGER ),
  1308. };
  1309. typedescription_t variant_t::m_SaveFloat[] =
  1310. {
  1311. DEFINE_FIELD( flVal, FIELD_FLOAT ),
  1312. };
  1313. typedescription_t variant_t::m_SaveEHandle[] =
  1314. {
  1315. DEFINE_FIELD( eVal, FIELD_EHANDLE ),
  1316. };
  1317. typedescription_t variant_t::m_SaveString[] =
  1318. {
  1319. DEFINE_FIELD( iszVal, FIELD_STRING ),
  1320. };
  1321. typedescription_t variant_t::m_SaveColor[] =
  1322. {
  1323. DEFINE_FIELD( rgbaVal, FIELD_COLOR32 ),
  1324. };
  1325. #undef classNameTypedef
  1326. //
  1327. // Struct for saving and restoring vector variants, since they are
  1328. // stored as float[3] and we want to take advantage of position vector
  1329. // fixup across level transitions.
  1330. //
  1331. #define classNameTypedef variant_savevector_t // to satisfy DEFINE... macros
  1332. struct variant_savevector_t
  1333. {
  1334. Vector vecSave;
  1335. };
  1336. typedescription_t variant_t::m_SaveVector[] =
  1337. {
  1338. // Just here to shut up ClassCheck
  1339. // DEFINE_ARRAY( vecVal, FIELD_FLOAT, 3 ),
  1340. DEFINE_FIELD( vecSave, FIELD_VECTOR ),
  1341. };
  1342. typedescription_t variant_t::m_SavePositionVector[] =
  1343. {
  1344. DEFINE_FIELD( vecSave, FIELD_POSITION_VECTOR ),
  1345. };
  1346. #undef classNameTypedef
  1347. #define classNameTypedef variant_savevmatrix_t // to satisfy DEFINE... macros
  1348. struct variant_savevmatrix_t
  1349. {
  1350. VMatrix matSave;
  1351. };
  1352. typedescription_t variant_t::m_SaveVMatrix[] =
  1353. {
  1354. DEFINE_FIELD( matSave, FIELD_VMATRIX ),
  1355. };
  1356. typedescription_t variant_t::m_SaveVMatrixWorldspace[] =
  1357. {
  1358. DEFINE_FIELD( matSave, FIELD_VMATRIX_WORLDSPACE ),
  1359. };
  1360. #undef classNameTypedef
  1361. #define classNameTypedef variant_savevmatrix3x4_t // to satisfy DEFINE... macros
  1362. struct variant_savevmatrix3x4_t
  1363. {
  1364. matrix3x4_t matSave;
  1365. };
  1366. typedescription_t variant_t::m_SaveMatrix3x4Worldspace[] =
  1367. {
  1368. DEFINE_FIELD( matSave, FIELD_MATRIX3X4_WORLDSPACE ),
  1369. };
  1370. #undef classNameTypedef
  1371. class CVariantSaveDataOps : public CDefSaveRestoreOps
  1372. {
  1373. // saves the entire array of variables
  1374. virtual void Save( const SaveRestoreFieldInfo_t &fieldInfo, ISave *pSave )
  1375. {
  1376. variant_t *var = (variant_t*)fieldInfo.pField;
  1377. int type = var->FieldType();
  1378. pSave->WriteInt( &type, 1 );
  1379. switch ( var->FieldType() )
  1380. {
  1381. case FIELD_VOID:
  1382. break;
  1383. case FIELD_BOOLEAN:
  1384. pSave->WriteFields( fieldInfo.pTypeDesc->fieldName, var, NULL, variant_t::m_SaveBool, 1 );
  1385. break;
  1386. case FIELD_INTEGER:
  1387. pSave->WriteFields( fieldInfo.pTypeDesc->fieldName, var, NULL, variant_t::m_SaveInt, 1 );
  1388. break;
  1389. case FIELD_FLOAT:
  1390. pSave->WriteFields( fieldInfo.pTypeDesc->fieldName, var, NULL, variant_t::m_SaveFloat, 1 );
  1391. break;
  1392. case FIELD_EHANDLE:
  1393. pSave->WriteFields( fieldInfo.pTypeDesc->fieldName, var, NULL, variant_t::m_SaveEHandle, 1 );
  1394. break;
  1395. case FIELD_STRING:
  1396. pSave->WriteFields( fieldInfo.pTypeDesc->fieldName, var, NULL, variant_t::m_SaveString, 1 );
  1397. break;
  1398. case FIELD_COLOR32:
  1399. pSave->WriteFields( fieldInfo.pTypeDesc->fieldName, var, NULL, variant_t::m_SaveColor, 1 );
  1400. break;
  1401. case FIELD_VECTOR:
  1402. {
  1403. variant_savevector_t Temp;
  1404. var->Vector3D(Temp.vecSave);
  1405. pSave->WriteFields( fieldInfo.pTypeDesc->fieldName, &Temp, NULL, variant_t::m_SaveVector, 1 );
  1406. break;
  1407. }
  1408. case FIELD_POSITION_VECTOR:
  1409. {
  1410. variant_savevector_t Temp;
  1411. var->Vector3D(Temp.vecSave);
  1412. pSave->WriteFields( fieldInfo.pTypeDesc->fieldName, &Temp, NULL, variant_t::m_SavePositionVector, 1 );
  1413. break;
  1414. }
  1415. default:
  1416. Warning( "Bad type %d in saved variant_t\n", var->FieldType() );
  1417. Assert(0);
  1418. }
  1419. }
  1420. // restores a single instance of the variable
  1421. virtual void Restore( const SaveRestoreFieldInfo_t &fieldInfo, IRestore *pRestore )
  1422. {
  1423. variant_t *var = (variant_t*)fieldInfo.pField;
  1424. *var = variant_t();
  1425. var->fieldType = (_fieldtypes)pRestore->ReadInt();
  1426. switch ( var->fieldType )
  1427. {
  1428. case FIELD_VOID:
  1429. break;
  1430. case FIELD_BOOLEAN:
  1431. pRestore->ReadFields( fieldInfo.pTypeDesc->fieldName, var, NULL, variant_t::m_SaveBool, 1 );
  1432. break;
  1433. case FIELD_INTEGER:
  1434. pRestore->ReadFields( fieldInfo.pTypeDesc->fieldName, var, NULL, variant_t::m_SaveInt, 1 );
  1435. break;
  1436. case FIELD_FLOAT:
  1437. pRestore->ReadFields( fieldInfo.pTypeDesc->fieldName, var, NULL, variant_t::m_SaveFloat, 1 );
  1438. break;
  1439. case FIELD_EHANDLE:
  1440. pRestore->ReadFields( fieldInfo.pTypeDesc->fieldName, var, NULL, variant_t::m_SaveEHandle, 1 );
  1441. break;
  1442. case FIELD_STRING:
  1443. pRestore->ReadFields( fieldInfo.pTypeDesc->fieldName, var, NULL, variant_t::m_SaveString, 1 );
  1444. break;
  1445. case FIELD_COLOR32:
  1446. pRestore->ReadFields( fieldInfo.pTypeDesc->fieldName, var, NULL, variant_t::m_SaveColor, 1 );
  1447. break;
  1448. case FIELD_VECTOR:
  1449. {
  1450. variant_savevector_t Temp;
  1451. pRestore->ReadFields( fieldInfo.pTypeDesc->fieldName, &Temp, NULL, variant_t::m_SaveVector, 1 );
  1452. var->SetVector3D(Temp.vecSave);
  1453. break;
  1454. }
  1455. case FIELD_POSITION_VECTOR:
  1456. {
  1457. variant_savevector_t Temp;
  1458. pRestore->ReadFields( fieldInfo.pTypeDesc->fieldName, &Temp, NULL, variant_t::m_SavePositionVector, 1 );
  1459. var->SetPositionVector3D(Temp.vecSave);
  1460. break;
  1461. }
  1462. default:
  1463. Warning( "Bad type %d in saved variant_t\n", var->FieldType() );
  1464. Assert(0);
  1465. break;
  1466. }
  1467. }
  1468. virtual bool IsEmpty( const SaveRestoreFieldInfo_t &fieldInfo )
  1469. {
  1470. // check all the elements of the array (usually only 1)
  1471. variant_t *var = (variant_t*)fieldInfo.pField;
  1472. for ( int i = 0; i < fieldInfo.pTypeDesc->fieldSize; i++, var++ )
  1473. {
  1474. if ( var->FieldType() != FIELD_VOID )
  1475. return 0;
  1476. }
  1477. // variant has no data
  1478. return 1;
  1479. }
  1480. virtual void MakeEmpty( const SaveRestoreFieldInfo_t &fieldInfo )
  1481. {
  1482. // Don't no how to. This is okay, since objects of this type
  1483. // are always born clean before restore, and not reused
  1484. }
  1485. };
  1486. CVariantSaveDataOps g_VariantSaveDataOps;
  1487. ISaveRestoreOps *variantFuncs = &g_VariantSaveDataOps;
  1488. /////////////////////// entitylist /////////////////////
  1489. CUtlMemoryPool g_EntListMemPool( sizeof(entitem_t), 256, CUtlMemoryPool::GROW_NONE, "g_EntListMemPool" );
  1490. #include "tier0/memdbgoff.h"
  1491. void *entitem_t::operator new( size_t stAllocateBlock )
  1492. {
  1493. return g_EntListMemPool.Alloc( stAllocateBlock );
  1494. }
  1495. void *entitem_t::operator new( size_t stAllocateBlock, int nBlockUse, const char *pFileName, int nLine )
  1496. {
  1497. return g_EntListMemPool.Alloc( stAllocateBlock );
  1498. }
  1499. void entitem_t::operator delete( void *pMem )
  1500. {
  1501. g_EntListMemPool.Free( pMem );
  1502. }
  1503. #include "tier0/memdbgon.h"
  1504. CEntityList::CEntityList()
  1505. {
  1506. m_pItemList = NULL;
  1507. m_iNumItems = 0;
  1508. }
  1509. CEntityList::~CEntityList()
  1510. {
  1511. // remove all items from the list
  1512. entitem_t *next, *e = m_pItemList;
  1513. while ( e != NULL )
  1514. {
  1515. next = e->pNext;
  1516. delete e;
  1517. e = next;
  1518. }
  1519. m_pItemList = NULL;
  1520. }
  1521. void CEntityList::AddEntity( CBaseEntity *pEnt )
  1522. {
  1523. // check if it's already in the list; if not, add it
  1524. entitem_t *e = m_pItemList;
  1525. while ( e != NULL )
  1526. {
  1527. if ( e->hEnt == pEnt )
  1528. {
  1529. // it's already in the list
  1530. return;
  1531. }
  1532. if ( e->pNext == NULL )
  1533. {
  1534. // we've hit the end of the list, so tack it on
  1535. e->pNext = new entitem_t;
  1536. e->pNext->hEnt = pEnt;
  1537. e->pNext->pNext = NULL;
  1538. m_iNumItems++;
  1539. return;
  1540. }
  1541. e = e->pNext;
  1542. }
  1543. // empty list
  1544. m_pItemList = new entitem_t;
  1545. m_pItemList->hEnt = pEnt;
  1546. m_pItemList->pNext = NULL;
  1547. m_iNumItems = 1;
  1548. }
  1549. void CEntityList::DeleteEntity( CBaseEntity *pEnt )
  1550. {
  1551. // find the entry in the list and delete it
  1552. entitem_t *prev = NULL, *e = m_pItemList;
  1553. while ( e != NULL )
  1554. {
  1555. // delete the link if it's the matching entity OR if the link is NULL
  1556. if ( e->hEnt == pEnt || e->hEnt == NULL )
  1557. {
  1558. if ( prev )
  1559. {
  1560. prev->pNext = e->pNext;
  1561. }
  1562. else
  1563. {
  1564. m_pItemList = e->pNext;
  1565. }
  1566. delete e;
  1567. m_iNumItems--;
  1568. // REVISIT: Is this correct? Is this just here to clean out dead EHANDLEs?
  1569. // restart the loop
  1570. e = m_pItemList;
  1571. prev = NULL;
  1572. continue;
  1573. }
  1574. prev = e;
  1575. e = e->pNext;
  1576. }
  1577. }