void CClientState::PacketEnd()
{
	//
	// we don't know if it is ok to save a demo message until
	// after we have parsed the frame
	//

	// Play any sounds we received this packet
	CL_DispatchSounds();
	
	// Did we get any messages this tick (i.e., did we call PreEntityPacketReceived)?
	if ( GetServerTickCount() != m_nDeltaTick )
		return;

	// How many commands total did we run this frame
	int commands_acknowledged = command_ack - last_command_ack;

//	COM_Log( "cl.log", "Server ack'd %i commands this frame\n", commands_acknowledged );

	//Msg( "%i/%i CL_PostReadMessages:  last ack %i most recent %i acked %i commands\n", 
	//	host_framecount, cl.tickcount,
	//	cl.last_command_ack, 
	//	cl.netchan->outgoing_sequence - 1,
	//	commands_acknowledged );

	// Highest command parsed from messages
	last_command_ack = command_ack;
	
	// Let prediction copy off pristine data and report any errors, etc.
	g_pClientSidePrediction->PostNetworkDataReceived( commands_acknowledged );

#ifndef _XBOX
	demoaction->DispatchEvents();
#endif
}
void CReplayRagdollRecorder::StopRecordingRagdollAtIndex( Iterator_t nIndex )
{
	// No longer recording - compute duration
	RagdollSimulationData_t* pData = m_lstRagdollsToRecord[ nIndex ];

	// Does duration need to be set?
	if ( pData->m_nDuration < 0 )
	{
		pData->m_nDuration = GetServerTickCount() - pData->m_nStartTick;		Assert( pData->m_nDuration > 0 );
	}

	// Remove it from the recording list
	m_lstRagdollsToRecord.Unlink( nIndex );
}
bool CClientState::ProcessPacketEntities( SVC_PacketEntities *msg )
{
	CL_PreprocessEntities(); // setup client prediction

	if ( !msg->m_bIsDelta )
	{
		// Delta too old or is initial message
#ifndef _XBOX			
		// we can start recording now that we've received an uncompressed packet
		demorecorder->SetSignonState( SIGNONSTATE_FULL );
#endif
		// Tell prediction that we're recreating entities due to an uncompressed packet arriving
		if ( g_pClientSidePrediction  )
		{
			g_pClientSidePrediction->OnReceivedUncompressedPacket();
		}
	}
	else
	{
		if ( m_nDeltaTick == -1  )
		{
			// we requested a full update but still got a delta compressed packet. ignore it.
			return true;
		}
	}
	
	TRACE_PACKET(( "CL Receive (%d <-%d)\n", m_nCurrentSequence, msg->m_nDeltaFrom ));
	TRACE_PACKET(( "CL Num Ents (%d)\n", msg->m_nUpdatedEntries ));

	if ( g_pLocalNetworkBackdoor )
	{
		if ( m_nSignonState == SIGNONSTATE_SPAWN  )
		{	
			// We are done with signon sequence.
			SetSignonState( SIGNONSTATE_FULL, m_nServerCount );
		}

		// ignore message, all entities are transmitted using fast local memcopy routines
		m_nDeltaTick = GetServerTickCount();
		return true;
	}
	
	if ( !CL_ProcessPacketEntities ( msg ) )
		return false;

	return CBaseClientState::ProcessPacketEntities( msg );
}
void RagdollSimulationData_t::Record()
{
	Assert( m_pEntity->m_pRagdoll );

	// Allocate a frame
	RagdollSimulationFrame_t* pNewFrame = RagdollSimulationFrame_t::Alloc( m_nNumBones );
	if ( !pNewFrame )
		return;

	// Set the current tick
	pNewFrame->nTick = GetServerTickCount();

	// Add new frame to list of frames
	m_lstFrames.AddToTail( pNewFrame );

	// Compute parent transform
	matrix3x4_t parentTransform;
	Vector vRootPosition = m_pEntity->GetRenderOrigin();
	QAngle angRootAngles = m_pEntity->GetRenderAngles();
	AngleMatrix( angRootAngles, vRootPosition, parentTransform );

//	debugoverlay->AddCoordFrameOverlay( parentTransform, 100 );

	// Cache off root position/orientation
	pNewFrame->vRootPosition = vRootPosition;
	pNewFrame->angRootAngles = angRootAngles;

	// Compute actual ragdoll bones
	matrix3x4_t* pBones = gs_BoneCache;
	_ComputeRagdollBones( m_pEntity->m_pRagdoll->GetRagdoll(), parentTransform, pBones, pNewFrame->pPositions, pNewFrame->pAngles );

	// Draw bones
	if ( replay_ragdoll_dbg.GetBool() )
	{
		DrawBones( pBones, m_pEntity->m_pRagdoll->RagdollBoneCount(), m_pEntity->m_pRagdoll->GetRagdoll(), 255, 0, 0, m_pEntity );
	}
}
bool CHLTVClientState::ProcessPacketEntities( SVC_PacketEntities *entmsg )
{
	CClientFrame *oldFrame = NULL;

#ifdef _HLTVTEST
	if ( g_RecvDecoders.Count() == 0 )
		return false;
#endif

	if ( entmsg->m_bIsDelta )
	{
		if ( GetServerTickCount() == entmsg->m_nDeltaFrom )
		{
			Host_Error( "Update self-referencing, connection dropped.\n" );
			return false;
		}

		// Otherwise, mark where we are valid to and point to the packet entities we'll be updating from.
		oldFrame = m_pHLTV->GetClientFrame( entmsg->m_nDeltaFrom );
	}

	// create new empty snapshot
	CFrameSnapshot* pSnapshot = framesnapshotmanager->CreateEmptySnapshot( GetServerTickCount(), entmsg->m_nMaxEntries );

	Assert( m_pNewClientFrame == NULL );
	
	m_pNewClientFrame = new CClientFrame( pSnapshot );

	Assert( entmsg->m_nBaseline >= 0 && entmsg->m_nBaseline < 2 );

	if ( entmsg->m_bUpdateBaseline )
	{
		// server requested to use this snapshot as baseline update
		int nUpdateBaseline = (entmsg->m_nBaseline == 0) ? 1 : 0;
		CopyEntityBaseline( entmsg->m_nBaseline, nUpdateBaseline );

		// send new baseline acknowledgement(as reliable)
		CLC_BaselineAck baseline( GetServerTickCount(), entmsg->m_nBaseline );
		m_NetChannel->SendNetMsg( baseline, true );
	}

	// copy classes and serial numbers from current frame
	if ( m_pCurrentClientFrame )
	{
		CFrameSnapshot* pLastSnapshot = m_pCurrentClientFrame->GetSnapshot();
		CFrameSnapshotEntry *pEntry = pSnapshot->m_pEntities;
		CFrameSnapshotEntry *pLastEntry = pLastSnapshot->m_pEntities;

		Assert( pLastSnapshot->m_nNumEntities <= pSnapshot->m_nNumEntities );

		for ( int i = 0; i<pLastSnapshot->m_nNumEntities; i++ )
		{
			pEntry->m_nSerialNumber = pLastEntry->m_nSerialNumber; 
			pEntry->m_pClass = pLastEntry->m_pClass;

			pEntry++;
			pLastEntry++;
		}
	}

	CEntityReadInfo u;
	u.m_pBuf = &entmsg->m_DataIn;
	u.m_pFrom = oldFrame;
	u.m_pTo = m_pNewClientFrame;
	u.m_bAsDelta = entmsg->m_bIsDelta;
	u.m_nHeaderCount = entmsg->m_nUpdatedEntries;
	u.m_nBaseline = entmsg->m_nBaseline;
	u.m_bUpdateBaselines = entmsg->m_bUpdateBaseline;

	ReadPacketEntities( u );

	// adjust reference count to be 1
	pSnapshot->ReleaseReference();

	return CBaseClientState::ProcessPacketEntities( entmsg );
}