Esempio n. 1
0
void UTIL_DecodeICE( unsigned char * buffer, int size, const unsigned char *key)
{
	if ( !key )
		return;

	IceKey ice( 0 ); // level 0 = 64bit key
	ice.set( key ); // set key

	int blockSize = ice.blockSize();

	unsigned char *temp = (unsigned char *)_alloca( PAD_NUMBER( size, blockSize ) );
	unsigned char *p1 = buffer;
	unsigned char *p2 = temp;
				
	// encrypt data in 8 byte blocks
	int bytesLeft = size;
	while ( bytesLeft >= blockSize )
	{
		ice.decrypt( p1, p2 );
		bytesLeft -= blockSize;
		p1+=blockSize;
		p2+=blockSize;
	}

	// copy encrypted data back to original buffer
	Q_memcpy( buffer, temp, size-bytesLeft );
}
bool CHLTVClientState::ProcessVoiceData( SVC_VoiceData *msg )
{
	int	 size = PAD_NUMBER( Bits2Bytes(msg->m_nLength), 4);
	byte *buffer = (byte*) stackalloc( size );
	msg->m_DataIn.ReadBits( buffer, msg->m_nLength );
	msg->m_DataOut = buffer;

	return m_pHLTV->SendNetMsg( *msg ); // relay to server
}
bool PackedEntity::AllocAndCopyPadded( const void *pData, unsigned long size, PackedDataAllocator *pAllocator )
{
	m_Data.Free();
	
	unsigned long nBytes = PAD_NUMBER( size, 4 );
	if ( pAllocator->Alloc( nBytes, m_Data ) )
	{
		void *pDest = m_Data.Lock();
		if ( pDest )
		{
			memcpy( pDest, pData, size );
			m_Data.Unlock();
			SetNumBits( nBytes * 8 );
			return true;
		}
	}

	return false;
}
//-----------------------------------------------------------------------------
// Writes the compressed packet of entities to all clients
//-----------------------------------------------------------------------------
void SV_ComputeClientPacks( 
	int clientCount, 
	client_t** clients,
	CFrameSnapshot *snapshot, 
	client_frame_t **pPack
	)
{
	VPROF( "SV_ComputeClientPacks" );

	
	ClientPackInfo_t info[MAX_CLIENTS];

	// Do some setup for each client
	int	iClient;
	for (iClient = 0; iClient < clientCount; ++iClient)
	{
		ClientPackInfo_t *pInfo = &info[iClient];


		// This helps handle it if they turn cl_LocalNetworkBackdoor on and off (which is useful to do for profiling).
		SV_HandleLocalNetworkBackdoorChange( clients[iClient] );

		// This will force network string table updates for local client to go through the backdoor if it's active
		SV_CheckDirectUpdate( clients[iClient] );

		SV_ComputeClientPackInfo( clients[iClient], pInfo );

		// This is the frame we are creating, i.e., the next
		// frame after the last one that the client acknowledged
		client_frame_t& frame = clients[iClient]->frames[clients[iClient]->netchan.outgoing_sequence & SV_UPDATE_MASK];
		pPack[iClient] = &frame;

		SV_SetupPack( pPack[iClient], snapshot );

		// Clear the 'transmit edict' bits for this ent for this client.
		memset( pInfo->m_EdictBits, 0, PAD_NUMBER( sv.num_edicts, 8 ) / 8 );
		pInfo->m_pPVS = pInfo->m_PVS;
		pInfo->m_pEdictBits = pInfo->m_EdictBits;

		// Since area to area visibility is determined by each player's PVS, copy
		//  the area network lookups into the ClientPackInfo_t
		pInfo->m_AreasNetworked.RemoveAll();
		int areaCount = g_AreasNetworked.Count();
		for ( int i = 0; i < areaCount; i++ )
		{
			pInfo->m_AreasNetworked.AddToTail( g_AreasNetworked[ i ] );
		}
	}


	// Figure out which entities should be sent.
	int validEdicts[MAX_EDICTS];
	int nValidEdicts = 0;
	for ( int iEdict=0; iEdict < sv.num_edicts; iEdict++ )
	{
		edict_t* ent = SV_GetEdictToTransmit( iEdict, snapshot );
		if ( !ent || !ent->m_pEnt )
			continue;

		// Get the edict send table
		SendTable* pSendTable = GetEntSendTable( ent );
		assert( pSendTable );
		if ( !pSendTable )
			continue;

		validEdicts[nValidEdicts++] = iEdict;

		for ( int iClient=0; iClient < clientCount; iClient++ )
		{		
			ClientPackInfo_t *pInfo = &info[iClient];
			Assert( pInfo );

			int areaCount = pInfo->m_AreasNetworked.Count();

			for ( int iArea=0; iArea < areaCount; iArea++ )
			{
				// If the edict is already marked to send to this client, we don't need to call CheckTransmit on it.
				if ( pInfo->WillTransmit( iEdict ) )
					break;

				pInfo->m_iArea = pInfo->m_AreasNetworked[ iArea ];
				CServerDTITimer timer( pSendTable, SERVERDTI_SHOULDTRANSMIT );
				ent->m_pEnt->CheckTransmit( pInfo );
			}
		}
	}
		

#ifndef SWDS
	int saveTicks = cl.tickcount;
#endif

	if ( g_pLocalNetworkBackdoor )
	{
		g_pLocalNetworkBackdoor->StartEntityStateUpdate();

#ifndef SWDS
		cl.tickcount = sv.tickcount;
		g_ClientGlobalVariables.tickcount = cl.tickcount;
		g_ClientGlobalVariables.curtime = cl.gettime();
#endif
	}
	

	// Send client all active entities in the pvs
	for ( int iValidEdict=0; iValidEdict < nValidEdicts; iValidEdict++ )
	{
		int e = validEdicts[iValidEdict];
		edict_t* ent = SV_GetEdictToTransmit(e, snapshot);
		SendTable* pSendTable = GetEntSendTable( ent );

		// Check to see if the entity changed this frame...
		EntityChange_t changeType = ent->m_pEnt->DetectNetworkStateChanges();
		
		ServerDTI_RegisterNetworkStateChange( pSendTable, changeType );

		// Have we packed this entity this frame?
		bool packedThisEntity = false;
		IServerEntity *serverEntity = ent->GetIServerEntity();
		if ( serverEntity )
		{
			serverEntity->SetSentLastFrame( false );
		}

		// Compute the entity bit + byte for the entity_in_pvs bitfield
		int entityByte = e >> 3;
		byte entityBit = ( 1 << ( e & 7 ) );

		for (int i = 0; i < clientCount; ++i )
		{
			ClientPackInfo_t *pInfo = &info[i];

			if ( g_pLocalNetworkBackdoor )
			{
				// this is a bit of a hack to ensure that we get a "preview" of the
				//  packet timstamp that the server will send so that things that
				//  are encoded relative to packet time will be correct


				int serialNum = ent->m_pEnt->GetRefEHandle().GetSerialNumber() & (1 << NUM_NETWORKED_EHANDLE_SERIAL_NUMBER_BITS) - 1;

				if( pInfo->WillTransmit( e ) )
				{
					CServerDTITimer timer( pSendTable, SERVERDTI_ENCODE );
					
					// If we're using the fast path for a single-player game, just pass the entity
					// directly over to the client.
					ServerClass *pClass = ent->m_pEnt->GetServerClass();
					g_pLocalNetworkBackdoor->EntState( e, serialNum, pClass->m_ClassID, pSendTable, ent->m_pEnt, changeType != ENTITY_CHANGE_NONE );

					// Indicate we've actually put the changes into the pack
					ent->m_pEnt->ResetNetworkStateChanges();
				}
				else
				{
					// Notify the client that the ent is still alive, but its ShouldTransmit returned false.
					g_pLocalNetworkBackdoor->EntityDormant( e, serialNum );
				}
			}
			else
			{
				if( !pInfo->WillTransmit( e ) )
					continue;

				// Mark that this player will have seen this entity created
				// (i.e., sent, at least once)
				ent->entity_created |= info[i].m_ClientBit;
				pPack[i]->entity_in_pvs[ entityByte ] |= entityBit;

				// Check to see if it's already been packed this frame...
				// If it hasn't, then pack it in, baby!
				if ( !packedThisEntity )
				{
					packedThisEntity = true;
					SV_PackEntity( e, ent, pSendTable, changeType, snapshot );
					ent->m_pEnt->ResetNetworkStateChanges();
				}
			}

			// We've got one more entity in this pack.
			++pPack[i]->entities.num_entities;

			// Now this is our biggest ent index in the pack
			pPack[i]->entities.max_entities = e;
		}
	}

	if ( g_pLocalNetworkBackdoor )
	{
		g_pLocalNetworkBackdoor->EndEntityStateUpdate();

#ifndef SWDS
		cl.tickcount = saveTicks;
		g_ClientGlobalVariables.tickcount = cl.tickcount;
		g_ClientGlobalVariables.curtime = cl.gettime();
#endif
	}
}