Beispiel #1
0
/*
=======================
CL_SendConnectPacket

We have gotten a challenge from the server, so try and
connect.
======================
*/
void CL_SendConnectPacket (void)
{
	netadr_t	adr;
	int32_t		port;

	if (!NET_StringToAdr (cls.servername, &adr))
	{
		Com_Printf ("Bad server address\n");
		cls.connect_time = 0;
		return;
	}
	if (adr.port == 0)
		adr.port = BigShort (PORT_SERVER);

	port = Cvar_VariableValue ("qport");
	userinfo_modified = false;

	// if in compatibility mode, lie to server about this
	// client's protocol, but exclude localhost for this.
	if (cl_servertrick->value && strcmp(cls.servername, "localhost"))
		Netchan_OutOfBandPrint (NS_CLIENT, adr, "connect %i %i %i \"%s\"\n",
			OLD_PROTOCOL_VERSION, port, cls.challenge, Cvar_Userinfo() );
	else
		Netchan_OutOfBandPrint (NS_CLIENT, adr, "connect %i %i %i \"%s\"\n",
			PROTOCOL_VERSION, port, cls.challenge, Cvar_Userinfo() );
}
Beispiel #2
0
/*
 * We have gotten a challenge from the server, so try and
 * connect.
 */
void
CL_SendConnectPacket(void)
{
	netadr_t adr;
	int port;

	memset(&adr, 0, sizeof(adr));

	if (!NET_StringToAdr(cls.servername, &adr))
	{
		Com_Printf("Bad server address\n");
		cls.connect_time = 0;
		return;
	}

	if (adr.port == 0)
	{
		adr.port = BigShort(PORT_SERVER);
	}

	port = Cvar_VariableValue("qport");

	userinfo_modified = false;

	Netchan_OutOfBandPrint(NS_CLIENT, adr, "connect %i %i %i \"%s\"\n",
			PROTOCOL_VERSION, port, cls.challenge, Cvar_Userinfo());
}
Beispiel #3
0
/**
 * @note Only call @c CL_Connect if there is no connection yet (@c cls.netStream is @c nullptr)
 * @sa CL_Disconnect
 * @sa CL_SendChangedUserinfos
 */
static void CL_Connect (void)
{
	Com_SetUserinfoModified(false);

	assert(!cls.netStream);

	if (cls.servername[0] != '\0') {
		assert(cls.serverport[0] != '\0');
		Com_Printf("Connecting to %s %s...\n", cls.servername, cls.serverport);
		cls.netStream = NET_Connect(cls.servername, cls.serverport, CL_FreeClientStream);
	} else {
		Com_Printf("Connecting to localhost...\n");
		cls.netStream = NET_ConnectToLoopBack(CL_FreeClientStream);
	}

	if (cls.netStream) {
		char info[MAX_INFO_STRING];
		NET_OOB_Printf(cls.netStream, SV_CMD_CONNECT " %i \"%s\"\n", PROTOCOL_VERSION, Cvar_Userinfo(info, sizeof(info)));
		cls.connectTime = CL_Milliseconds();
	} else {
		if (cls.servername[0] != '\0') {
			assert(cls.serverport[0]);
			Com_Printf("Could not connect to %s %s\n", cls.servername, cls.serverport);
		} else {
			Com_Printf("Could not connect to localhost\n");
		}
	}
}
Beispiel #4
0
/**
 * @brief Send the userinfo to the server (and to all other clients)
 * when they changed (CVAR_USERINFO)
 * @sa CL_Connect
 */
static void CL_SendChangedUserinfos (void)
{
	/* send a userinfo update if needed */
	if (cls.state < ca_connected)
		return;
	if (!Com_IsUserinfoModified())
		return;
	char info[MAX_INFO_STRING];
	const char* userInfo = Cvar_Userinfo(info, sizeof(info));
	dbuffer msg(strlen(userInfo) + 2);
	NET_WriteByte(&msg, clc_userinfo);
	NET_WriteString(&msg, userInfo);
	NET_WriteMsg(cls.netStream, msg);
	Com_SetUserinfoModified(false);
}
Beispiel #5
0
void
CL_Userinfo_f(void)
{
	Com_Printf("User info settings:\n");
	Info_Print(Cvar_Userinfo());
}
Beispiel #6
0
/*
=================
CL_SendCmd
=================
*/
void CL_SendCmd (void)
{
	sizebuf_t	buf;
	byte		data[128];
	int			i;
	usercmd_t	*cmd, *oldcmd;
	usercmd_t	nullcmd;
	int			checksumIndex;

	// clear buffer
	memset (&buf, 0, sizeof(buf));

	// build a command even if not connected

	// save this command off for prediction
	i = cls.netchan.outgoing_sequence & (CMD_BACKUP-1);
	cmd = &cl.cmds[i];
	cl.cmd_time[i] = cls.realtime;	// for netgraph ping calculation

	*cmd = CL_CreateCmd ();

	cl.cmd = *cmd;

	if (cls.state == ca_disconnected || cls.state == ca_connecting)
		return;

	if (cls.state == ca_connected)
	{
		if (cls.netchan.message.cursize	|| curtime - cls.netchan.last_sent > 1000 )
			Netchan_Transmit (&cls.netchan, 0, buf.data);	
		return;
	}

	// send a userinfo update if needed
	if (userinfo_modified)
	{
		CL_FixUpGender();
		userinfo_modified = false;
		MSG_WriteByte (&cls.netchan.message, clc_userinfo);
		MSG_WriteString (&cls.netchan.message, Cvar_Userinfo() );
	}

	SZ_Init (&buf, data, sizeof(data));

	// Knightmare- removed this, put ESC-only substitute in keys.c
	/*if (cmd->buttons && cl.cinematictime > 0 && !cl.attractloop 
		&& cls.realtime - cl.cinematictime > 1000)
	{	// skip the rest of the cinematic
		SCR_FinishCinematic ();
	}*/

	// begin a client move command
	MSG_WriteByte (&buf, clc_move);

	// save the position for a checksum byte
	checksumIndex = buf.cursize;
	MSG_WriteByte (&buf, 0);

	// let the server know what the last frame we
	// got was, so the next message can be delta compressed
	if (cl_nodelta->value || !cl.frame.valid || cls.demowaiting)
		MSG_WriteLong (&buf, -1);	// no compression
	else
		MSG_WriteLong (&buf, cl.frame.serverframe);

	// send this and the previous cmds in the message, so
	// if the last packet was dropped, it can be recovered
	i = (cls.netchan.outgoing_sequence-2) & (CMD_BACKUP-1);
	cmd = &cl.cmds[i];
	memset (&nullcmd, 0, sizeof(nullcmd));
	MSG_WriteDeltaUsercmd (&buf, &nullcmd, cmd);
	oldcmd = cmd;

	i = (cls.netchan.outgoing_sequence-1) & (CMD_BACKUP-1);
	cmd = &cl.cmds[i];
	MSG_WriteDeltaUsercmd (&buf, oldcmd, cmd);
	oldcmd = cmd;

	i = (cls.netchan.outgoing_sequence) & (CMD_BACKUP-1);
	cmd = &cl.cmds[i];
	MSG_WriteDeltaUsercmd (&buf, oldcmd, cmd);

	// calculate a checksum over the move commands
	buf.data[checksumIndex] = COM_BlockSequenceCRCByte(
		buf.data + checksumIndex + 1, buf.cursize - checksumIndex - 1,
		cls.netchan.outgoing_sequence);

	//
	// deliver the message
	//
	Netchan_Transmit (&cls.netchan, buf.cursize, buf.data);	
}
Beispiel #7
0
/*
=======================
CL_SendConnectPacket

We have gotten a challenge from the server, so try and
connect.
======================
*/
void CL_SendConnectPacket( void )
{
	netadr_t	adr;
	int	port;

	if( !NET_StringToAdr( cls.servername, &adr ))
	{
		MsgDev( D_INFO, "CL_SendConnectPacket: bad server address\n");
		cls.connect_time = 0;
		return;
	}

	if( adr.port == 0 ) adr.port = BF_BigShort( PORT_SERVER );
	port = Cvar_VariableValue( "net_qport" );

	userinfo->modified = false;
	Netchan_OutOfBandPrint( NS_CLIENT, adr, "connect %i %i %i \"%s\"\n", PROTOCOL_VERSION, port, cls.challenge, Cvar_Userinfo( ));
}
Beispiel #8
0
/*
===================
CL_WritePacket

Create and send the command packet to the server
Including both the reliable commands and the usercmds
===================
*/
void CL_WritePacket( void )
{
	sizebuf_t		buf;
	qboolean		send_command = false;
	byte		data[MAX_CMD_BUFFER];
	int		i, from, to, key, size;
	int		numbackup = 2;
	int		numcmds;
	int		newcmds;
	int		cmdnumber;
	
	// don't send anything if playing back a demo
	if( cls.demoplayback || cls.state == ca_cinematic )
		return;

	if( cls.state == ca_disconnected || cls.state == ca_connecting )
		return;

	CL_ComputePacketLoss ();

#ifndef _DEBUG
	if( cl_cmdrate->value < MIN_CMD_RATE )
	{
		Cvar_SetFloat( "cl_cmdrate", MIN_CMD_RATE );
	}
#endif
	Q_memset( data, 0, MAX_CMD_BUFFER );
	BF_Init( &buf, "ClientData", data, sizeof( data ));

	// Determine number of backup commands to send along
	numbackup = bound( 0, cl_cmdbackup->integer, MAX_BACKUP_COMMANDS );
	if( cls.state == ca_connected ) numbackup = 0;

	// Check to see if we can actually send this command

	// In single player, send commands as fast as possible
	// Otherwise, only send when ready and when not choking bandwidth
	if(( cl.maxclients == 1 ) || ( NET_IsLocalAddress( cls.netchan.remote_address ) && !host_limitlocal->integer ))
		send_command = true;
	else if(( host.realtime >= cls.nextcmdtime ) && Netchan_CanPacket( &cls.netchan ))
		send_command = true;

	if( cl.force_send_usercmd )
	{
		send_command = true;
		cl.force_send_usercmd = false;
	}

	if(( cls.netchan.outgoing_sequence - cls.netchan.incoming_acknowledged ) >= CL_UPDATE_MASK )
	{
		if(( host.realtime - cls.netchan.last_received ) > CONNECTION_PROBLEM_TIME )
		{
			Con_NPrintf( 1, "^3Warning:^1 Connection Problem^7\n" );
			cl.validsequence = 0;
		}
	}

	if( cl_nodelta->integer )
	{
		cl.validsequence = 0;
	}
	
	// send a userinfo update if needed
	if( userinfo->modified )
	{
		BF_WriteByte( &cls.netchan.message, clc_userinfo );
		BF_WriteString( &cls.netchan.message, Cvar_Userinfo( ));
	}
		
	if( send_command )
	{
		int	outgoing_sequence;
	
		if( cl_cmdrate->integer > 0 )
			cls.nextcmdtime = host.realtime + ( 1.0f / cl_cmdrate->value );
		else cls.nextcmdtime = host.realtime; // always able to send right away

		if( cls.lastoutgoingcommand == -1 )
		{
			outgoing_sequence = cls.netchan.outgoing_sequence;
			cls.lastoutgoingcommand = cls.netchan.outgoing_sequence;
		}
		else outgoing_sequence = cls.lastoutgoingcommand + 1;

		// begin a client move command
		BF_WriteByte( &buf, clc_move );

		// save the position for a checksum byte
		key = BF_GetRealBytesWritten( &buf );
		BF_WriteByte( &buf, 0 );

		// write packet lossage percentation
		BF_WriteByte( &buf, cls.packet_loss );

		// say how many backups we'll be sending
		BF_WriteByte( &buf, numbackup );

		// how many real commands have queued up
		newcmds = ( cls.netchan.outgoing_sequence - cls.lastoutgoingcommand );

		// put an upper/lower bound on this
		newcmds = bound( 0, newcmds, MAX_TOTAL_CMDS );
		if( cls.state == ca_connected ) newcmds = 0;
	
		BF_WriteByte( &buf, newcmds );

		numcmds = newcmds + numbackup;
		from = -1;

		for( i = numcmds - 1; i >= 0; i-- )
		{
			cmdnumber = ( cls.netchan.outgoing_sequence - i ) & CL_UPDATE_MASK;

			to = cmdnumber;
			CL_WriteUsercmd( &buf, from, to );
			from = to;

			if( BF_CheckOverflow( &buf ))
				Host_Error( "CL_Move, overflowed command buffer (%i bytes)\n", MAX_CMD_BUFFER );
		}

		// calculate a checksum over the move commands
		size = BF_GetRealBytesWritten( &buf ) - key - 1;
		buf.pData[key] = CRC32_BlockSequence( buf.pData + key + 1, size, cls.netchan.outgoing_sequence );

		// message we are constructing.
		i = cls.netchan.outgoing_sequence & CL_UPDATE_MASK;
	
		// determine if we need to ask for a new set of delta's.
		if( cl.validsequence && (cls.state == ca_active) && !( cls.demorecording && cls.demowaiting ))
		{
			cl.delta_sequence = cl.validsequence;

			BF_WriteByte( &buf, clc_delta );
			BF_WriteByte( &buf, cl.validsequence & 0xFF );
		}
		else
		{
			// request delta compression of entities
			cl.delta_sequence = -1;
		}

		if( BF_CheckOverflow( &buf ))
		{
			Host_Error( "CL_Move, overflowed command buffer (%i bytes)\n", MAX_CMD_BUFFER );
		}

		// remember outgoing command that we are sending
		cls.lastoutgoingcommand = cls.netchan.outgoing_sequence;

		// composite the rest of the datagram..
		if( BF_GetNumBitsWritten( &cls.datagram ) <= BF_GetNumBitsLeft( &buf ))
			BF_WriteBits( &buf, BF_GetData( &cls.datagram ), BF_GetNumBitsWritten( &cls.datagram ));
		BF_Clear( &cls.datagram );

		// deliver the message (or update reliable)
		Netchan_Transmit( &cls.netchan, BF_GetNumBytesWritten( &buf ), BF_GetData( &buf ));
	}
	else
	{
		// increment sequence number so we can detect that we've held back packets.
		cls.netchan.outgoing_sequence++;
	}

	if( cls.demorecording )
	{
		// Back up one because we've incremented outgoing_sequence each frame by 1 unit
		cmdnumber = ( cls.netchan.outgoing_sequence - 1 ) & CL_UPDATE_MASK;
		CL_WriteDemoUserCmd( cmdnumber );
	}

	// update download/upload slider.
	Netchan_UpdateProgress( &cls.netchan );
}
Beispiel #9
0
/*
==============
CL_Userinfo_f
==============
*/
void CL_Userinfo_f( void )
{
	Msg( "User info settings:\n" );
	Info_Print( Cvar_Userinfo( ));
	Msg( "Total %i symbols\n", Q_strlen( Cvar_Userinfo( )));
}
Beispiel #10
0
void CL_SendCmd(void)
{
  sizebuf_t buf;
  byte data[128];
  int i;
  usercmd_t *cmd, *oldcmd;
  usercmd_t nullcmd;
  int checksumIndex;

  memset(&buf, 0, sizeof(buf));

  /* save this command off for prediction */
  i = cls.netchan.outgoing_sequence & (CMD_BACKUP - 1);
  cmd = &cl.cmds[i];
  cl.cmd_time[i] = cls.realtime; /* for netgraph ping calculation */

  CL_FinalizeCmd();

  cl.cmd = *cmd;

  if ((cls.state == ca_disconnected) || (cls.state == ca_connecting)) {
    return;
  }

  if (cls.state == ca_connected) {
    if (cls.netchan.message.cursize || (curtime - cls.netchan.last_sent > 1000)) {
      Netchan_Transmit(&cls.netchan, 0, buf.data);
    }

    return;
  }

  /* send a userinfo update if needed */
  if (userinfo_modified) {
    CL_FixUpGender();
    userinfo_modified = false;
    MSG_WriteByte(&cls.netchan.message, clc_userinfo);
    MSG_WriteString(&cls.netchan.message, Cvar_Userinfo());
  }

  SZ_Init(&buf, data, sizeof(data));

  /* begin a client move command */
  MSG_WriteByte(&buf, clc_move);

  /* save the position for a checksum byte */
  checksumIndex = buf.cursize;
  MSG_WriteByte(&buf, 0);

  /* let the server know what the last frame we
     got was, so the next message can be delta
     compressed */
  if (cl_nodelta->value || !cl.frame.valid) {
    MSG_WriteLong(&buf, -1); /* no compression */
  } else {
    MSG_WriteLong(&buf, cl.frame.serverframe);
  }

  /* send this and the previous cmds in the message, so
     if the last packet was dropped, it can be recovered */
  i = (cls.netchan.outgoing_sequence - 2) & (CMD_BACKUP - 1);
  cmd = &cl.cmds[i];
  memset(&nullcmd, 0, sizeof(nullcmd));
  MSG_WriteDeltaUsercmd(&buf, &nullcmd, cmd);
  oldcmd = cmd;

  i = (cls.netchan.outgoing_sequence - 1) & (CMD_BACKUP - 1);
  cmd = &cl.cmds[i];
  MSG_WriteDeltaUsercmd(&buf, oldcmd, cmd);
  oldcmd = cmd;

  i = (cls.netchan.outgoing_sequence) & (CMD_BACKUP - 1);
  cmd = &cl.cmds[i];
  MSG_WriteDeltaUsercmd(&buf, oldcmd, cmd);

  /* calculate a checksum over the move commands */
  buf.data[checksumIndex] = COM_BlockSequenceCRCByte(buf.data + checksumIndex + 1, buf.cursize - checksumIndex - 1,
                                                     cls.netchan.outgoing_sequence);

  /* deliver the message */
  Netchan_Transmit(&cls.netchan, buf.cursize, buf.data);

  /* Reinit the current cmd buffer */
  cmd = &cl.cmds[cls.netchan.outgoing_sequence & (CMD_BACKUP - 1)];
  memset(cmd, 0, sizeof(*cmd));
}
Beispiel #11
0
/**
 * @brief Prints the current userinfo string to the game console
 * @sa SV_UserInfo_f
 */
static void CL_UserInfo_f (void)
{
	Com_Printf("User info settings:\n");
	char info[MAX_INFO_STRING];
	Info_Print(Cvar_Userinfo(info, sizeof(info)));
}