예제 #1
0
//-----------------------------------------------------------------------------
// 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();
}