void CHLTVClientState::CopyNewEntity( 
	CEntityReadInfo &u,
	int iClass,
	int iSerialNum
	)
{
	ServerClass *pServerClass = SV_FindServerClass( iClass );
	Assert( pServerClass );
	
	ClientClass *pClientClass = GetClientClass( iClass );
	Assert( pClientClass );

	const int ent = u.m_nNewEntity;

	// copy class & serial
	CFrameSnapshot *pSnapshot = u.m_pTo->GetSnapshot();
	pSnapshot->m_pEntities[ent].m_nSerialNumber = iSerialNum;
	pSnapshot->m_pEntities[ent].m_pClass = pServerClass;

	// Get either the static or instance baseline.
	const void *pFromData = NULL;
	int nFromBits = 0;
	int nFromTick = 0;	// MOTODO get tick when baseline last changed

	PackedEntity *baseline = u.m_bAsDelta ? GetEntityBaseline( u.m_nBaseline, ent ) : NULL;

	if ( baseline && baseline->m_pClientClass == pClientClass )
	{
		Assert( !baseline->IsCompressed() );
		pFromData = baseline->GetData();
		nFromBits = baseline->GetNumBits();
	}
	else
	{
		// Every entity must have a static or an instance baseline when we get here.
		ErrorIfNot(
			GetClassBaseline( iClass, &pFromData, &nFromBits ),
			("HLTV_CopyNewEntity: GetDynamicBaseline(%d) failed.", iClass)
		);
		nFromBits *= 8; // convert to bits
	}

	// create new ChangeFrameList containing all properties set as changed
	int nFlatProps = SendTable_GetNumFlatProps( pServerClass->m_pTable );
	IChangeFrameList *pChangeFrame = NULL;
	
	if ( !m_bSaveMemory )
	{
		pChangeFrame = AllocChangeFrameList( nFlatProps, nFromTick );
	}

	// Now make a PackedEntity and store the new packed data in there.
	PackedEntity *pPackedEntity = framesnapshotmanager->CreatePackedEntity( pSnapshot, ent );
	pPackedEntity->SetChangeFrameList( pChangeFrame );
	pPackedEntity->SetServerAndClientClass( pServerClass, pClientClass );

	// Make space for the baseline data.
	char packedData[MAX_PACKEDENTITY_DATA];
	bf_read fromBuf( "HLTV_ReadEnterPVS1", pFromData, Bits2Bytes( nFromBits ), nFromBits );
	bf_write writeBuf( "HLTV_ReadEnterPVS2", packedData, sizeof( packedData ) );

	int changedProps[MAX_DATATABLE_PROPS];
	
	// decode basline, is compressed against zero values 
	int nChangedProps = RecvTable_MergeDeltas( pClientClass->m_pRecvTable, &fromBuf, 
		u.m_pBuf, &writeBuf, -1, false, changedProps );

	// update change tick in ChangeFrameList
	if ( pChangeFrame )
	{
		pChangeFrame->SetChangeTick( changedProps, nChangedProps, pSnapshot->m_nTickCount );
	}

	if ( u.m_bUpdateBaselines )
	{
		SetEntityBaseline( (u.m_nBaseline==0)?1:0, pClientClass, u.m_nNewEntity, packedData, writeBuf.GetNumBytesWritten() );
	}

	pPackedEntity->AllocAndCopyPadded( packedData, writeBuf.GetNumBytesWritten() );

	// If ent doesn't think it's in PVS, signal that it is
	Assert( u.m_pTo->last_entity <= ent );
	u.m_pTo->last_entity = ent;
	u.m_pTo->transmit_entity.Set( ent );
}
void CHLTVClientState::ReadDeltaEnt( CEntityReadInfo &u )
{
	const int i = u.m_nNewEntity;
	CFrameSnapshot *pFromSnapshot =	u.m_pFrom->GetSnapshot();

	CFrameSnapshot *pSnapshot = u.m_pTo->GetSnapshot();

	Assert( i < pFromSnapshot->m_nNumEntities );
	pSnapshot->m_pEntities[i] = pFromSnapshot->m_pEntities[i];
	
	PackedEntity *pToPackedEntity = framesnapshotmanager->CreatePackedEntity( pSnapshot, i );

	// WARNING! get pFromPackedEntity after new pPackedEntity has been created, otherwise pointer may be wrong
	PackedEntity *pFromPackedEntity = framesnapshotmanager->GetPackedEntity( pFromSnapshot, i );

	pToPackedEntity->SetServerAndClientClass( pFromPackedEntity->m_pServerClass, pFromPackedEntity->m_pClientClass );

	// create a copy of the pFromSnapshot ChangeFrameList
	IChangeFrameList* pChangeFrame = NULL;
 
	if ( !m_bSaveMemory )
	{
		pChangeFrame = pFromPackedEntity->GetChangeFrameList()->Copy();
		pToPackedEntity->SetChangeFrameList( pChangeFrame );
	}

	// Make space for the baseline data.
	char packedData[MAX_PACKEDENTITY_DATA];
	const void *pFromData;
	int nFromBits;

	if ( pFromPackedEntity->IsCompressed() )
	{
		pFromData = m_pHLTV->UncompressPackedEntity( pFromPackedEntity, nFromBits );
	}
	else
	{
		pFromData = pFromPackedEntity->GetData();
		nFromBits = pFromPackedEntity->GetNumBits();
	}

	bf_read fromBuf( "HLTV_ReadEnterPVS1", pFromData, Bits2Bytes( nFromBits ), nFromBits );
	bf_write writeBuf( "HLTV_ReadEnterPVS2", packedData, sizeof( packedData ) );

	int changedProps[MAX_DATATABLE_PROPS];
	
	// decode baseline, is compressed against zero values 
	int nChangedProps = RecvTable_MergeDeltas( pToPackedEntity->m_pClientClass->m_pRecvTable,
		&fromBuf, u.m_pBuf, &writeBuf, -1, false, changedProps );

	// update change tick in ChangeFrameList
	if ( pChangeFrame )
	{
		pChangeFrame->SetChangeTick( changedProps, nChangedProps, pSnapshot->m_nTickCount );
	}

	if ( m_bSaveMemory )
	{
		int bits = writeBuf.GetNumBitsWritten();

		const char *compressedData = m_pHLTV->CompressPackedEntity( 
			pToPackedEntity->m_pServerClass,
			(char*)writeBuf.GetData(),
			bits );

		// store as compressed data and don't use mem pools
		pToPackedEntity->AllocAndCopyPadded( compressedData, Bits2Bytes(bits) );
		pToPackedEntity->SetCompressed();
	}
	else
	{
		// store as normal
		pToPackedEntity->AllocAndCopyPadded( packedData, writeBuf.GetNumBytesWritten() );
	}

	u.m_pTo->last_entity = u.m_nNewEntity;
	u.m_pTo->transmit_entity.Set( u.m_nNewEntity );

	u.NextOldEntity();
}