static inline void SV_PackEntity( 
	int edictIdx, 
	edict_t* ent, 
	SendTable* pSendTable,
	EntityChange_t changeType, 
	CFrameSnapshot *pSnapshot )
{
	int iSerialNum = pSnapshot->m_Entities[ edictIdx ].m_nSerialNumber;

	// Check to see if this entity specifies its changes.
	// If so, then try to early out making the fullpack
	bool bUsedPrev = false;
	if ( changeType == ENTITY_CHANGE_NONE )
	{
		// Now this may not work if we didn't previously send a packet;
		// if not, then we gotta compute it
		bUsedPrev = framesnapshot->UsePreviouslySentPacket( pSnapshot, edictIdx, iSerialNum );
	}
					  
	if ( !bUsedPrev || sv_debugmanualmode.GetInt() )
	{
		// First encode the entity's data.
		char packedData[MAX_PACKEDENTITY_DATA];
		bf_write writeBuf( "SV_PackEntity->writeBuf", packedData, sizeof( packedData ) );
		
		// (avoid constructor overhead).
		unsigned char tempData[ sizeof( CSendProxyRecipients ) * MAX_DATATABLE_PROXIES ];
		CUtlMemory< CSendProxyRecipients > recip( (CSendProxyRecipients*)tempData, pSendTable->GetNumDataTableProxies() );

		if( !SendTable_Encode( pSendTable, ent->m_pEnt, &writeBuf, NULL, edictIdx, &recip ) )
		{							 
			Host_Error( "SV_PackEntity: SendTable_Encode returned false (ent %d).\n", edictIdx );
		}

		SV_EnsureInstanceBaseline( edictIdx, packedData, writeBuf.GetNumBytesWritten() );
			
		int nFlatProps = SendTable_GetNumFlatProps( pSendTable );
		IChangeFrameList *pChangeFrame;

		// If this entity was previously in there, then it should have a valid IChangeFrameList 
		// which we can delta against to figure out which properties have changed.
		//
		// If not, then we want to setup a new IChangeFrameList.
		PackedEntity *pPrevFrame = framesnapshot->GetPreviouslySentPacket( edictIdx, pSnapshot->m_Entities[ edictIdx ].m_nSerialNumber );
		if ( pPrevFrame )
		{
			// Calculate a delta.
			bf_read bfPrev( "SV_PackEntity->bfPrev", pPrevFrame->LockData(), pPrevFrame->GetNumBytes() );
			bf_read bfNew( "SV_PackEntity->bfNew", packedData, writeBuf.GetNumBytesWritten() );
			
			int deltaProps[MAX_DATATABLE_PROPS];

			int nChanges = SendTable_CalcDelta(
				pSendTable, 
				pPrevFrame->LockData(), pPrevFrame->GetNumBits(),
				packedData,	writeBuf.GetNumBitsWritten(),
				
				deltaProps,
				ARRAYSIZE( deltaProps ),

				edictIdx
				);

			// If it's non-manual-mode, but we detect that there are no changes here, then just
			// use the previous pSnapshot if it's available (as though the entity were manual mode).
			// It would be interesting to hook here and see how many non-manual-mode entities 
			// are winding up with no changes.
			if ( nChanges == 0 )
			{
				if ( changeType == ENTITY_CHANGE_NONE )
				{
					for ( int iDeltaProp=0; iDeltaProp < nChanges; iDeltaProp++ )
					{
						Msg( "Entity %d (class '%s') reported ENTITY_CHANGE_NONE but '%s' changed.\n", 
							edictIdx,
							STRING( ent->classname ),
							pSendTable->GetProp( deltaProps[iDeltaProp] )->GetName() );

					}
				}
				else
				{
					if ( pPrevFrame->CompareRecipients( recip ) )
					{
						if ( framesnapshot->UsePreviouslySentPacket( pSnapshot, edictIdx, iSerialNum ) )
							return;
					}
				}
			}
		
			// Ok, now snag the changeframe from the previous frame and update the 'last frame changed'
			// for the properties in the delta.
			pChangeFrame = pPrevFrame->SnagChangeFrameList();
			
			ErrorIfNot( pChangeFrame && pChangeFrame->GetNumProps() == nFlatProps,
				("SV_PackEntity: SnagChangeFrameList returned null")
			);

			pChangeFrame->SetChangeTick( deltaProps, nChanges, pSnapshot->m_nTickNumber );
		}
		else
		{
			// Ok, init the change frames for the first time.
			pChangeFrame = AllocChangeFrameList( nFlatProps, pSnapshot->m_nTickNumber );
		}

		// Now make a PackedEntity and store the new packed data in there.
		PackedEntity *pCurFrame = framesnapshot->CreatePackedEntity( pSnapshot, edictIdx );
		pCurFrame->SetChangeFrameList( pChangeFrame );
		pCurFrame->m_nEntityIndex = edictIdx;
		pCurFrame->m_pSendTable = pSendTable;
		pCurFrame->AllocAndCopyPadded( packedData, writeBuf.GetNumBytesWritten(), &g_PackedDataAllocator );
		pCurFrame->SetRecipients( recip );
	}
}