void CPhysicsListenerCollision::event_friction_pair_created( IVP_Friction_Core_Pair *pair )
{
	corepair_t test(pair);
	unsigned short index = m_pairList.Find( test );
	if ( m_pairList.IsValidIndex( index ) )
	{
		corepair_t &save = m_pairList.Element(index);
		// found this one already, update the time
		if ( save.lastImpactTime.get_seconds() > pair->last_impact_time_pair.get_seconds() )
		{
			pair->last_impact_time_pair = save.lastImpactTime;
		}
		else
		{
			save.lastImpactTime = pair->last_impact_time_pair;
		}
	}
	else
	{
		if ( m_pairList.Count() < 16 )
		{
			m_pairList.Insert( test );
		}
	}
}
char const* CUtlSymbolTable::String( CUtlSymbol id ) const
{
	if (!id.IsValid()) 
		return "";
	
	Assert( m_Lookup.IsValidIndex((UtlSymId_t)id) );
	return StringFromIndex( m_Lookup[id] );
}
//-----------------------------------------------------------------------------
// Delete a managed image
//-----------------------------------------------------------------------------
void CSchemeManager::DeleteImage( const char *pImageName )
{
	if ( !pImageName )
		return;

	// set up to search for the bitmap
	CachedBitmapHandle_t searchBitmap;
	searchBitmap.bitmap = NULL;

	s_pszSearchString = pImageName;
	int i = m_Bitmaps.Find( searchBitmap );
	if ( m_Bitmaps.IsValidIndex( i ) )
	{
		delete m_Bitmaps[i].bitmap;	
		m_Bitmaps.RemoveAt( i );
	}
}
//-----------------------------------------------------------------------------
// Purpose: returns a pointer to an image
//-----------------------------------------------------------------------------
IImage *CSchemeManager::GetImage(const char *imageName, bool hardwareFiltered)
{
	if ( !imageName || strlen(imageName) <= 0 ) // frame icons and the like are in the scheme file and may not be defined, so if this is null then fail silently
	{
		return NULL; 
	}

	// set up to search for the bitmap
	CachedBitmapHandle_t searchBitmap;
	searchBitmap.bitmap = NULL;

	// Prepend 'vgui/'. Resource files try to load images assuming they live in the vgui directory.
	// Used to do this in Bitmap::Bitmap, moved so that the s_pszSearchString is searching for the
	// filename with 'vgui/' already added.
	char szFileName[256];

	if ( Q_stristr( imageName, ".pic" ) )
	{
		Q_snprintf( szFileName, sizeof(szFileName), "%s", imageName );
	}
	else
	{
		Q_snprintf( szFileName, sizeof(szFileName), "vgui/%s", imageName );
	}

	s_pszSearchString = szFileName;

	int i = m_Bitmaps.Find(searchBitmap);
	if (m_Bitmaps.IsValidIndex(i))
	{
		return m_Bitmaps[i].bitmap;
	}

	// couldn't find the image, try and load it
	CachedBitmapHandle_t bitmap = { new Bitmap(szFileName, hardwareFiltered) };
	m_Bitmaps.Insert(bitmap);
	return bitmap.bitmap;
}
void CCombatCharVisCache::FrameUpdatePreEntityThink()
{
	//	Msg( "test: %d/%d\n", m_nHitCount, m_nTestCount );

	// Lazy retirement of vis cache
	// NOTE: 256 was chosen heuristically based on a playthrough where 200
	// was the max # in the viscache where nothing could be retired.
	if ( m_VisCache.Count() < 256 )
		return;

	int nMaxIndex = m_VisCache.MaxElement() - 1;
	for ( int i = 0; i < 8; ++i )
	{
		int n = RandomInt( 0, nMaxIndex );
		if ( !m_VisCache.IsValidIndex( n ) )
			continue;

		const VisCacheEntry_t &entry = m_VisCache[n];
		if ( !entry.m_hEntity1.IsValid() || !entry.m_hEntity2.IsValid() || ( gpGlobals->curtime - entry.m_flTime > 10.0f ) )
		{
			m_VisCache.RemoveAt( n );
		}
	}
}
//-----------------------------------------------------------------------------
// Purpose: Checks to see if we should resend any reliable packets
//-----------------------------------------------------------------------------
void CTrackerNET::CheckReliablePacketSending()
{
	float time = m_pThreads->GetTime();

	// reliable packets are held in the m_ReliableMessages queue in the order that they were sent
	// if a packet is resent, it is moved to the end of the queue
	// packets are also checked at this time to see if they have been acknowledged
	while (m_ReliableMessages.Count())
	{
		// get the first message
		int index = m_ReliableMessages.Head();

		// get the message
		SentMessage_t &msg = m_ReliableMessages[index];

		// check the resend time, if it's not time to resend then we have nothing more to do 
		if (msg.resendTime > time)
			break;	

		// get the network target for this message
		if (!m_TargetList.IsValidIndex(msg.networkTargetHandle) 
			|| !m_TargetList.IsInList(msg.networkTargetHandle) 
			|| m_TargetList[msg.networkTargetHandle].targetID != msg.networkTargetID)
		{
			// message's target has been removed, kill
			if (msg.message)
			{
				msg.message->deleteThis();
			}
			m_ReliableMessages.Remove(index);
			continue;
		}

		NetworkTarget_t &target = m_TargetList[msg.networkTargetHandle];

		// check to see if it's already been acknowledged
		if (msg.sequenceNumber <= target.outgoingAcknowledged)
		{
			// message has been acknowledged, kill
			if (msg.message)
			{
				msg.message->deleteThis();
			}
			m_ReliableMessages.Remove(index);

			// move onto next message
			continue;
		}

		// check to see if we should resend this packet
		msg.resendAttempt++;
		if (msg.resendAttempt < MAX_SEND_ATTEMPTS)
		{
			// only send the message if it's in the message send window
			if (msg.sequenceNumber < target.outgoingAcknowledged + MESSAGE_WINDOW)
			{
				WriteToLog("-> Resending '%d' (os:%d > %d) (%s)\n", msg.message->GetMsgID(), msg.sequenceNumber, target.outgoingAcknowledged, target.netAddress.ToStaticString());

				// send that it again
				InternalSendMessage(msg.message, &target, msg.sequenceNumber);
			}
			else
			{
				// hold back on sending the message
				WriteToLog("-> Holding back resend '%d' (os:%d > %d) (%s)\n", msg.message->GetMsgID(), msg.sequenceNumber, target.outgoingAcknowledged, target.netAddress.ToStaticString());
				msg.resendAttempt--;
			}

			// set the time before retrying again
			// send times: 0.0 1.5 1.5 1.5 (1.5) = 6.0 second timeout, 4 packets sent
			msg.resendTime = time + RESEND_TIME;

			// move it to the end of the list
			m_ReliableMessages.Unlink(index);
			m_ReliableMessages.LinkToTail(index);

			// next packet
			continue;
		}

		// target has failed to respond, remove the target and respond with a failed message
		WriteToLog("Could not deliver packet: %d (os:%d)\n", msg.message->GetMsgID(), msg.sequenceNumber);

		// send back a send failure message to the app
		// convert the send message into a receive message
		CSendMessage *sendMsg = dynamic_cast<CSendMessage *>(msg.message);
		if (sendMsg)
		{
			IBinaryBuffer *buf = sendMsg->GetBuffer();
			
			buf->SetPosition(buf->GetBufferData());
			buf->Advance(buf->GetReservedSize());
			CReceiveMessage *failMsg = new CReceiveMessage(buf, true);

			if (failMsg->IsValid())
			{
				failMsg->SetFailed();
				failMsg->SetNetAddress(target.netAddress);
				failMsg->SetSessionID(sendMsg->SessionID());

				int newIndex = m_FailedMsgs.AddToTail();
				FailedMsg_t &fmsg = m_FailedMsgs[newIndex];
				fmsg.message = failMsg;
			}
			else
			{
				delete failMsg;
			}
		}

		// target not responding, so cancel the connection
		// remove from target map
		int mapindex = FindTargetIndexByAddress(target.netAddress);
		assert(m_TargetMap.IsValidIndex(mapindex));
		m_TargetMap.RemoveAt(mapindex);

		// remove target from list
		m_TargetList.Remove(msg.networkTargetHandle);
		
		// message will automatically be delete since it's target is gone
	}
}
//-----------------------------------------------------------------------------
// Purpose: Creates a target address, for sending messages to reliably
//-----------------------------------------------------------------------------
int CTrackerNET::FindTarget(CNetAddress &address, int targetID, int sequenceNumber)
{
	bool createNew = true;
	NetworkTarget_t *target = NULL;
	int listIndex = 0;

	// find the address in the map
	int targetIndex = FindTargetIndexByAddress(address);
	if (m_TargetMap.IsValidIndex(targetIndex))
	{
		listIndex = m_TargetMap[targetIndex].targetIndex;
		target = &(m_TargetList[listIndex]);

		// make sure the targetID's match, otherwise the connection has been invalidated
		if (targetID == -1 || target->targetID == targetID)
		{
			return listIndex;
		}
		else
		{
			if (sequenceNumber == 1)
			{
				//!! reset the connection
				WriteToLog("-> Connection Reset (%d) (%d, %d)\n", sequenceNumber, targetID, target->targetID);
			}
			else
			{
				WriteToLog("-> Connection Restart (%d) (%d, %d)\n", sequenceNumber, targetID, target->targetID);
			}
			createNew = false;
		}
	}

	if (createNew)
	{
		// add a new connection to the end of the list
		listIndex = m_TargetList.AddToTail();
		target = &(m_TargetList[listIndex]);
		target->needAck = false;

		// add the target to the map
		TargetMapItem_t newItem;
		newItem.targetIndex = listIndex;
		newItem.netAddress = address;
		m_TargetMap.Insert(newItem);

		// ensure that it's the first one in the sequence
		if (sequenceNumber > 1)
		{
			WriteToLog("-> Contacted by unknown old connection (targetID:%d)\n", targetID);
		}
	}

	// append to the end of the list
	target->netAddress = address;

	// initialize sequence numbers
	target->outgoingSequence = 1;
	target->outgoingAcknowledged = 0;
	target->incomingSequence = 0;
	target->incomingAcknowledged = 0;

	if (sequenceNumber != -1)
	{
		// this is the first packet we've received, but from and old connection; so jump the correct sequence number
		target->incomingSequence = sequenceNumber - 1;
	}

//	target->createTime = m_pThreads->GetTime();
	if (targetID >= 0)
	{
		target->targetID = targetID;
	}
	else
	{
		target->targetID = RandomLong(1, MAX_RANDOM_RANGE);
	}

	if (createNew && targetID >= 0)
	{
		WriteToLog("Creating new target ID (%d)\n", target->targetID);
	}
	else
	{
		WriteToLog("Establishing connection to target ID (%d)\n", target->targetID);
	}

	return listIndex;
}