//----------------------------------------------------------------------------- // Performs the think function //----------------------------------------------------------------------------- void CClientThinkList::PerformThinkFunction( ThinkEntry_t *pEntry, float flCurtime ) { IClientThinkable *pThink = ClientEntityList().GetClientThinkableFromHandle( pEntry->m_hEnt ); if ( !pThink ) { RemoveThinkable( pEntry->m_hEnt ); return; } if ( pEntry->m_flNextClientThink == CLIENT_THINK_ALWAYS ) { // NOTE: The Think function here could call SetNextClientThink // which would cause it to be removed + readded into the list pThink->ClientThink(); } else if ( pEntry->m_flNextClientThink == FLT_MAX ) { // This is an entity that doesn't need to think again; remove it RemoveThinkable( pEntry->m_hEnt ); } else { Assert( pEntry->m_flNextClientThink <= flCurtime ); // Indicate we're not going to think again pEntry->m_flNextClientThink = FLT_MAX; // NOTE: The Think function here could call SetNextClientThink // which would cause it to be readded into the list pThink->ClientThink(); } // Set this after the Think calls in case they look at LastClientThink pEntry->m_flLastClientThink = flCurtime; }
void CClientThinkList::PerformThinkFunctions() { float curtime = gpGlobals->curtime; unsigned long iNext; for ( unsigned long iCur=m_ThinkEntries.Head(); iCur != m_ThinkEntries.InvalidIndex(); iCur = iNext ) { iNext = m_ThinkEntries.Next( iCur ); CThinkEntry *pEntry = &m_ThinkEntries[iCur]; IClientThinkable *pThink = ClientEntityList().GetClientThinkableFromHandle( pEntry->m_hEnt ); if ( pThink ) { if ( pEntry->m_flNextClientThink == CLIENT_THINK_ALWAYS ) { // NOTE: The Think function here could call SetNextClientThink // which would cause it to be removed + readded into the list pThink->ClientThink(); // NOTE: The Think() call can cause other things to be added to the Think // list, which could reallocate memory and invalidate the pEntry pointer pEntry = &m_ThinkEntries[iCur]; } else if ( pEntry->m_flNextClientThink < curtime ) { pEntry->m_flNextClientThink = curtime; // NOTE: The Think function here could call SetNextClientThink // which would cause it to be readded into the list pThink->ClientThink(); // NOTE: The Think() call can cause other things to be added to the Think // list, which could reallocate memory and invalidate the pEntry pointer pEntry = &m_ThinkEntries[iCur]; // If they haven't changed the think time, then it should be removed. if ( pEntry->m_flNextClientThink == curtime ) { RemoveThinkable( pEntry->m_hEnt ); } } Assert( pEntry == &m_ThinkEntries[iCur] ); // Set this after the Think calls in case they look at LastClientThink m_ThinkEntries[iCur].m_flLastClientThink = curtime; } else { // This should be almost impossible. When ClientEntityHandle_t's are versioned, // this should be totally impossible. Assert( false ); m_ThinkEntries.Remove( iCur ); } } // Clear out the client-side entity deletion list. CleanUpDeleteList(); }