示例#1
0
/*
=======================
SV_SendClientMessages
=======================
*/
void SV_SendClientMessages( void )
{
	sv_client_t	*cl;
	int		i;

	if( sv.state == ss_dead )
		return;

	// send a message to each connected client
	for( i = 0, cl = svs.clients; i < sv_maxclients->integer; i++, cl++ )
	{
		if( !cl->state ) continue;
			
		if( !cl->edict || (cl->edict->v.flags & (FL_FAKECLIENT|FL_SPECTATOR)))
			continue;

		// update any userinfo packets that have changed
		if( cl->sendinfo )
		{
			cl->sendinfo = false;
			SV_FullClientUpdate( cl, &sv.multicast );
		}
                    
		if( cl->sendmovevars )
		{
			cl->sendmovevars = false;
			SV_UpdatePhysinfo( cl, &sv.multicast );
                    }

		// if the reliable message overflowed, drop the client
		if( cl->netchan.message.overflowed )
		{
			MSG_Clear( &cl->netchan.message );
			MSG_Clear( &cl->reliable );
			MSG_Clear( &cl->datagram );
			SV_BroadcastPrintf( PRINT_HIGH, "%s overflowed\n", cl->name );
			SV_DropClient( cl );
			cl->send_message = true;
		}

		// only send messages if the client has sent one
		if( !cl->send_message ) continue;

		if( cl->state == cs_spawned )
		{
			// don't overrun bandwidth
			if( SV_RateDrop( cl )) continue;
			SV_SendClientDatagram( cl );
		}
		else
		{
			// just update reliable
			if( cl->netchan.message.cursize || svs.realtime - cl->netchan.last_sent > 1000 )
				Netchan_Transmit( &cl->netchan, 0, NULL );
		}

		// yes, message really sended 
		cl->send_message = false;
	}
}
示例#2
0
/*
* SV_SendClientMessages
*/
void SV_SendClientMessages( void )
{
	int i;
	client_t *client;

	// send a message to each connected client
	for( i = 0, client = svs.clients; i < sv_maxclients->integer; i++, client++ )
	{
		if( client->state == CS_FREE || client->state == CS_ZOMBIE )
			continue;

		if( client->edict && ( client->edict->r.svflags & SVF_FAKECLIENT ) )
		{
			client->lastSentFrameNum = sv.framenum;
			continue;
		}

		if( !client->tvclient ) {
			SV_UpdateActivity();
		}

		if( client->state == CS_SPAWNED )
		{
			if( !SV_SendClientDatagram( client ) )
			{
				Com_Printf( "Error sending message to %s: %s\n", client->name, NET_ErrorString() );
				if( client->reliable )
				{
					SV_DropClient( client, DROP_TYPE_GENERAL, "Error sending message: %s\n", NET_ErrorString() );
				}
			}
		}
		else
		{
			// send pending reliable commands, or send heartbeats for not timing out
			if( client->reliableSequence > client->reliableAcknowledge ||
				svs.realtime - client->lastPacketSentTime > 1000 )
			{
				SV_InitClientMessage( client, &tmpMessage, NULL, 0 );
				SV_AddReliableCommandsToMessage( client, &tmpMessage );
				if( !SV_SendMessageToClient( client, &tmpMessage ) )
				{
					Com_Printf( "Error sending message to %s: %s\n", client->name, NET_ErrorString() );
					if( client->reliable )
					{
						SV_DropClient( client, DROP_TYPE_GENERAL, "Error sending message: %s\n", NET_ErrorString() );
					}
				}
			}
		}
	}
}
示例#3
0
/*
=======================
SV_SendClientMessages
=======================
*/
void SV_SendClientMessages( void )
{
	sv_client_t	*cl;
	int		i;

	svs.currentPlayer = NULL;
	svs.currentPlayerNum = 0;

	if( sv.state == ss_dead )
		return;

	SV_UpdateToReliableMessages ();

	// send a message to each connected client
	for( i = 0, cl = svs.clients; i < sv_maxclients->integer; i++, cl++ )
	{
		if( !cl->state || cl->fakeclient )
			continue;

		if( cl->skip_message )
		{
			cl->skip_message = false;
			continue;
		}

		if( !host_limitlocal->integer && NET_IsLocalAddress( cl->netchan.remote_address ))
			cl->send_message = true;

		if( cl->state == cs_spawned )
		{
			// Try to send a message as soon as we can.
			// If the target time for sending is within the next frame interval ( based on last frame ),
			// trigger the send now. Note that in single player,
			// send_message is also set to true any time a packet arrives from the client.
			float	time_unti_next_message = cl->next_messagetime - (host.realtime + host.frametime);

			if( time_unti_next_message <= 0.0f )
				cl->send_message = true;

			// something got hosed
			if( time_unti_next_message > 2.0f )
				cl->send_message = true;
		}

		// if the reliable message overflowed, drop the client
		if( BF_CheckOverflow( &cl->netchan.message ))
		{
			BF_Clear( &cl->netchan.message );
			BF_Clear( &cl->datagram );
			SV_BroadcastPrintf( PRINT_HIGH, "%s overflowed\n", cl->name );
			MsgDev( D_WARN, "reliable overflow for %s\n", cl->name );
			SV_DropClient( cl );
			cl->send_message = true;
			cl->netchan.cleartime = 0;	// don't choke this message
		}
		else if( cl->send_message )
		{
			// If we haven't gotten a message in sv_failuretime seconds, then stop sending messages to this client
			// until we get another packet in from the client. This prevents crash/drop and reconnect where they are
			// being hosed with "sequenced packet without connection" packets.
			if(( host.realtime - cl->netchan.last_received ) > sv_failuretime->value )
				cl->send_message = false;
		}

		// only send messages if the client has sent one
		// and the bandwidth is not choked
		if( !cl->send_message ) continue;

		// Bandwidth choke active?
		if( !Netchan_CanPacket( &cl->netchan ))
		{
			cl->chokecount++;
			continue;
		}

		cl->send_message = false;

		// Now that we were able to send, reset timer to point to next possible send time.
		cl->next_messagetime = host.realtime + host.frametime + cl->cl_updaterate;

		if( cl->state == cs_spawned )
		{
			SV_SendClientDatagram( cl );
		}
		else
		{
			// just update reliable
			Netchan_Transmit( &cl->netchan, 0, NULL );
		}
	}

	// reset current client
	svs.currentPlayer = NULL;
	svs.currentPlayerNum = 0;
}