コード例 #1
0
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();
}
コード例 #2
0
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 );
}
コード例 #3
0
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 );
	}
}