diff options
Diffstat (limited to 'src/client/cl_main.c')
-rw-r--r-- | src/client/cl_main.c | 754 |
1 files changed, 572 insertions, 182 deletions
diff --git a/src/client/cl_main.c b/src/client/cl_main.c index 326bc5f6..444b877d 100644 --- a/src/client/cl_main.c +++ b/src/client/cl_main.c @@ -25,6 +25,26 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #include "client.h" #include <limits.h> +#ifdef USE_MUMBLE +#include "libmumblelink.h" +#endif + +#ifdef USE_MUMBLE +cvar_t *cl_useMumble; +cvar_t *cl_mumbleScale; +#endif + +#ifdef USE_VOIP +cvar_t *cl_voipUseVAD; +cvar_t *cl_voipVADThreshold; +cvar_t *cl_voipSend; +cvar_t *cl_voipSendTarget; +cvar_t *cl_voipGainDuringCapture; +cvar_t *cl_voipCaptureMult; +cvar_t *cl_voipShowMeter; +cvar_t *cl_voip; +#endif + cvar_t *cl_nodelta; cvar_t *cl_debugMove; @@ -37,7 +57,6 @@ cvar_t *rconAddress; cvar_t *cl_timeout; cvar_t *cl_maxpackets; cvar_t *cl_packetdup; -cvar_t *cl_master; cvar_t *cl_timeNudge; cvar_t *cl_showTimeDelta; cvar_t *cl_freezeDemo; @@ -123,6 +142,284 @@ void CL_CDDialog( void ) { cls.cddialog = qtrue; // start it next frame } +#ifdef USE_MUMBLE +static +void CL_UpdateMumble(void) +{ + vec3_t pos, forward, up; + float scale = cl_mumbleScale->value; + float tmp; + + if(!cl_useMumble->integer) + return; + + // !!! FIXME: not sure if this is even close to correct. + AngleVectors( cl.snap.ps.viewangles, forward, NULL, up); + + pos[0] = cl.snap.ps.origin[0] * scale; + pos[1] = cl.snap.ps.origin[2] * scale; + pos[2] = cl.snap.ps.origin[1] * scale; + + tmp = forward[1]; + forward[1] = forward[2]; + forward[2] = tmp; + + tmp = up[1]; + up[1] = up[2]; + up[2] = tmp; + + if(cl_useMumble->integer > 1) { + fprintf(stderr, "%f %f %f, %f %f %f, %f %f %f\n", + pos[0], pos[1], pos[2], + forward[0], forward[1], forward[2], + up[0], up[1], up[2]); + } + + mumble_update_coordinates(pos, forward, up); +} +#endif + + +#ifdef USE_VOIP +static +void CL_UpdateVoipIgnore(const char *idstr, qboolean ignore) +{ + if ((*idstr >= '0') && (*idstr <= '9')) { + const int id = atoi(idstr); + if ((id >= 0) && (id < MAX_CLIENTS)) { + clc.voipIgnore[id] = ignore; + CL_AddReliableCommand(va("voip %s %d", + ignore ? "ignore" : "unignore", id)); + Com_Printf("VoIP: %s ignoring player #%d\n", + ignore ? "Now" : "No longer", id); + } + } +} + +static +void CL_UpdateVoipGain(const char *idstr, float gain) +{ + if ((*idstr >= '0') && (*idstr <= '9')) { + const int id = atoi(idstr); + if (gain < 0.0f) + gain = 0.0f; + if ((id >= 0) && (id < MAX_CLIENTS)) { + clc.voipGain[id] = gain; + Com_Printf("VoIP: player #%d gain now set to %f\n", id, gain); + } + } +} + +void CL_Voip_f( void ) +{ + const char *cmd = Cmd_Argv(1); + const char *reason = NULL; + + if (cls.state != CA_ACTIVE) + reason = "Not connected to a server"; + else if (!clc.speexInitialized) + reason = "Speex not initialized"; + else if (!cl_connectedToVoipServer) + reason = "Server doesn't support VoIP"; + + if (reason != NULL) { + Com_Printf("VoIP: command ignored: %s\n", reason); + return; + } + + if (strcmp(cmd, "ignore") == 0) { + CL_UpdateVoipIgnore(Cmd_Argv(2), qtrue); + } else if (strcmp(cmd, "unignore") == 0) { + CL_UpdateVoipIgnore(Cmd_Argv(2), qfalse); + } else if (strcmp(cmd, "gain") == 0) { + CL_UpdateVoipGain(Cmd_Argv(2), atof(Cmd_Argv(3))); + } else if (strcmp(cmd, "muteall") == 0) { + Com_Printf("VoIP: muting incoming voice\n"); + CL_AddReliableCommand("voip muteall"); + clc.voipMuteAll = qtrue; + } else if (strcmp(cmd, "unmuteall") == 0) { + Com_Printf("VoIP: unmuting incoming voice\n"); + CL_AddReliableCommand("voip unmuteall"); + clc.voipMuteAll = qfalse; + } +} + + +static +void CL_VoipNewGeneration(void) +{ + // don't have a zero generation so new clients won't match, and don't + // wrap to negative so MSG_ReadLong() doesn't "fail." + clc.voipOutgoingGeneration++; + if (clc.voipOutgoingGeneration <= 0) + clc.voipOutgoingGeneration = 1; + clc.voipPower = 0.0f; + clc.voipOutgoingSequence = 0; +} + +/* +=============== +CL_CaptureVoip + +Record more audio from the hardware if required and encode it into Speex + data for later transmission. +=============== +*/ +static +void CL_CaptureVoip(void) +{ + const float audioMult = cl_voipCaptureMult->value; + const qboolean useVad = (cl_voipUseVAD->integer != 0); + qboolean initialFrame = qfalse; + qboolean finalFrame = qfalse; + +#if USE_MUMBLE + // if we're using Mumble, don't try to handle VoIP transmission ourselves. + if (cl_useMumble->integer) + return; +#endif + + if (!clc.speexInitialized) + return; // just in case this gets called at a bad time. + + if (clc.voipOutgoingDataSize > 0) + return; // packet is pending transmission, don't record more yet. + + if (cl_voipUseVAD->modified) { + Cvar_Set("cl_voipSend", (useVad) ? "1" : "0"); + cl_voipUseVAD->modified = qfalse; + } + + if ((useVad) && (!cl_voipSend->integer)) + Cvar_Set("cl_voipSend", "1"); // lots of things reset this. + + if (cl_voipSend->modified) { + qboolean dontCapture = qfalse; + if (cls.state != CA_ACTIVE) + dontCapture = qtrue; // not connected to a server. + else if (!cl_connectedToVoipServer) + dontCapture = qtrue; // server doesn't support VoIP. + else if (clc.demoplaying) + dontCapture = qtrue; // playing back a demo. + else if ( cl_voip->integer == 0 ) + dontCapture = qtrue; // client has VoIP support disabled. + else if ( audioMult == 0.0f ) + dontCapture = qtrue; // basically silenced incoming audio. + + cl_voipSend->modified = qfalse; + + if (dontCapture) { + cl_voipSend->integer = 0; + return; + } + + if (cl_voipSend->integer) { + initialFrame = qtrue; + } else { + finalFrame = qtrue; + } + } + + // try to get more audio data from the sound card... + + if (initialFrame) { + float gain = cl_voipGainDuringCapture->value; + if (gain < 0.0f) gain = 0.0f; else if (gain >= 1.0f) gain = 1.0f; + S_MasterGain(cl_voipGainDuringCapture->value); + S_StartCapture(); + CL_VoipNewGeneration(); + } + + if ((cl_voipSend->integer) || (finalFrame)) { // user wants to capture audio? + int samples = S_AvailableCaptureSamples(); + const int mult = (finalFrame) ? 1 : 12; // 12 == 240ms of audio. + + // enough data buffered in audio hardware to process yet? + if (samples >= (clc.speexFrameSize * mult)) { + // audio capture is always MONO16 (and that's what speex wants!). + // 2048 will cover 12 uncompressed frames in narrowband mode. + static int16_t sampbuffer[2048]; + float voipPower = 0.0f; + int speexFrames = 0; + int wpos = 0; + int pos = 0; + + if (samples > (clc.speexFrameSize * 12)) + samples = (clc.speexFrameSize * 12); + + // !!! FIXME: maybe separate recording from encoding, so voipPower + // !!! FIXME: updates faster than 4Hz? + + samples -= samples % clc.speexFrameSize; + S_Capture(samples, (byte *) sampbuffer); // grab from audio card. + + // this will probably generate multiple speex packets each time. + while (samples > 0) { + int16_t *sampptr = &sampbuffer[pos]; + int i, bytes; + + // preprocess samples to remove noise... + speex_preprocess_run(clc.speexPreprocessor, sampptr); + + // check the "power" of this packet... + for (i = 0; i < clc.speexFrameSize; i++) { + const float flsamp = (float) sampptr[i]; + const float s = fabs(flsamp); + voipPower += s * s; + sampptr[i] = (int16_t) ((flsamp) * audioMult); + } + + // encode raw audio samples into Speex data... + speex_bits_reset(&clc.speexEncoderBits); + speex_encode_int(clc.speexEncoder, sampptr, + &clc.speexEncoderBits); + bytes = speex_bits_write(&clc.speexEncoderBits, + (char *) &clc.voipOutgoingData[wpos+1], + sizeof (clc.voipOutgoingData) - (wpos+1)); + assert((bytes > 0) && (bytes < 256)); + clc.voipOutgoingData[wpos] = (byte) bytes; + wpos += bytes + 1; + + // look at the data for the next packet... + pos += clc.speexFrameSize; + samples -= clc.speexFrameSize; + speexFrames++; + } + + clc.voipPower = (voipPower / (32768.0f * 32768.0f * + ((float) (clc.speexFrameSize * speexFrames)))) * + 100.0f; + + if ((useVad) && (clc.voipPower < cl_voipVADThreshold->value)) { + CL_VoipNewGeneration(); // no "talk" for at least 1/4 second. + } else { + clc.voipOutgoingDataSize = wpos; + clc.voipOutgoingDataFrames = speexFrames; + + Com_DPrintf("VoIP: Send %d frames, %d bytes, %f power\n", + speexFrames, wpos, clc.voipPower); + + #if 0 + static FILE *encio = NULL; + if (encio == NULL) encio = fopen("voip-outgoing-encoded.bin", "wb"); + if (encio != NULL) { fwrite(clc.voipOutgoingData, wpos, 1, encio); fflush(encio); } + static FILE *decio = NULL; + if (decio == NULL) decio = fopen("voip-outgoing-decoded.bin", "wb"); + if (decio != NULL) { fwrite(sampbuffer, speexFrames * clc.speexFrameSize * 2, 1, decio); fflush(decio); } + #endif + } + } + } + + // User requested we stop recording, and we've now processed the last of + // any previously-buffered data. Pause the capture device, etc. + if (finalFrame) { + S_StopCapture(); + S_MasterGain(1.0f); + clc.voipPower = 0.0f; // force this value so it doesn't linger. + } +} +#endif /* ======================================================================= @@ -825,7 +1122,7 @@ void CL_MapLoading( void ) { Key_SetCatcher( 0 ); SCR_UpdateScreen(); clc.connectTime = -RETRANSMIT_TIMEOUT; - NET_StringToAdr( cls.servername, &clc.serverAddress); + NET_StringToAdr( cls.servername, &clc.serverAddress, NA_UNSPEC); // we don't need a challenge on the localhost CL_CheckForResend(); @@ -853,7 +1150,7 @@ CL_UpdateGUID update cl_guid using QKEY_FILE and optional prefix ==================== */ -static void CL_UpdateGUID( char *prefix, int prefix_len ) +static void CL_UpdateGUID( const char *prefix, int prefix_len ) { fileHandle_t f; int len; @@ -898,6 +1195,36 @@ void CL_Disconnect( qboolean showMainMenu ) { *clc.downloadTempName = *clc.downloadName = 0; Cvar_Set( "cl_downloadName", "" ); +#ifdef USE_MUMBLE + if (cl_useMumble->integer && mumble_islinked()) { + Com_Printf("Mumble: Unlinking from Mumble application\n"); + mumble_unlink(); + } +#endif + +#ifdef USE_VOIP + if (cl_voipSend->integer) { + int tmp = cl_voipUseVAD->integer; + cl_voipUseVAD->integer = 0; // disable this for a moment. + clc.voipOutgoingDataSize = 0; // dump any pending VoIP transmission. + Cvar_Set("cl_voipSend", "0"); + CL_CaptureVoip(); // clean up any state... + cl_voipUseVAD->integer = tmp; + } + + if (clc.speexInitialized) { + int i; + speex_bits_destroy(&clc.speexEncoderBits); + speex_encoder_destroy(clc.speexEncoder); + speex_preprocess_state_destroy(clc.speexPreprocessor); + for (i = 0; i < MAX_CLIENTS; i++) { + speex_bits_destroy(&clc.speexDecoderBits[i]); + speex_decoder_destroy(clc.speexDecoder[i]); + } + } + Cmd_RemoveCommand ("voip"); +#endif + if ( clc.demofile ) { FS_FCloseFile( clc.demofile ); clc.demofile = 0; @@ -932,6 +1259,11 @@ void CL_Disconnect( qboolean showMainMenu ) { // not connected to a pure server anymore cl_connectedToPureServer = qfalse; +#ifdef USE_VOIP + // not connected to voip server anymore. + cl_connectedToVoipServer = qfalse; +#endif + // Stop recording any video if( CL_VideoRecording( ) ) { // Finish rendering current frame @@ -986,7 +1318,7 @@ void CL_RequestMotd( void ) { return; } Com_Printf( "Resolving %s\n", MASTER_SERVER_NAME ); - if ( !NET_StringToAdr( MASTER_SERVER_NAME, &cls.updateServer ) ) { + if ( !NET_StringToAdr( MASTER_SERVER_NAME, &cls.updateServer, NA_IP ) ) { Com_Printf( "Couldn't resolve address\n" ); return; } @@ -1109,12 +1441,28 @@ CL_Connect_f */ void CL_Connect_f( void ) { char *server; - char serverString[ 22 ]; + const char *serverString; + int argc = Cmd_Argc(); + netadrtype_t family = NA_UNSPEC; - if ( Cmd_Argc() != 2 ) { - Com_Printf( "usage: connect [server]\n"); + if ( argc != 2 && argc != 3 ) { + Com_Printf( "usage: connect [-4|-6] server\n"); return; } + + if(argc == 2) + server = Cmd_Argv(1); + else + { + if(!strcmp(Cmd_Argv(1), "-4")) + family = NA_IP; + else if(!strcmp(Cmd_Argv(1), "-6")) + family = NA_IP6; + else + Com_Printf( "warning: only -4 or -6 as address type understood.\n"); + + server = Cmd_Argv(2); + } Cvar_Set("ui_singlePlayerActive", "0"); @@ -1124,8 +1472,6 @@ void CL_Connect_f( void ) { // clear any previous "server full" type messages clc.serverMessage[0] = 0; - server = Cmd_Argv (1); - if ( com_sv_running->integer && !strcmp( server, "localhost" ) ) { // if running a local server, kill it SV_Shutdown( "Server quit" ); @@ -1138,13 +1484,9 @@ void CL_Connect_f( void ) { CL_Disconnect( qtrue ); Con_Close(); - /* MrE: 2000-09-13: now called in CL_DownloadsComplete - CL_FlushMemory( ); - */ - Q_strncpyz( cls.servername, server, sizeof(cls.servername) ); - if (!NET_StringToAdr( cls.servername, &clc.serverAddress) ) { + if (!NET_StringToAdr(cls.servername, &clc.serverAddress, family) ) { Com_Printf ("Bad server address\n"); cls.state = CA_DISCONNECTED; return; @@ -1152,12 +1494,10 @@ void CL_Connect_f( void ) { if (clc.serverAddress.port == 0) { clc.serverAddress.port = BigShort( PORT_SERVER ); } - Com_sprintf( serverString, sizeof( serverString ), "%i.%i.%i.%i:%i", - clc.serverAddress.ip[0], clc.serverAddress.ip[1], - clc.serverAddress.ip[2], clc.serverAddress.ip[3], - BigShort( clc.serverAddress.port ) ); - - Com_Printf( "%s resolved to %s\n", cls.servername, serverString ); + + serverString = NET_AdrToStringwPort(clc.serverAddress); + + Com_Printf( "%s resolved to %s\n", cls.servername, serverString); if( cl_guidServerUniq->integer ) CL_UpdateGUID( serverString, strlen( serverString ) ); @@ -1224,7 +1564,7 @@ void CL_Rcon_f( void ) { return; } - NET_StringToAdr (rconAddress->string, &to); + NET_StringToAdr (rconAddress->string, &to, NA_UNSPEC); if (to.port == 0) { to.port = BigShort (PORT_SERVER); } @@ -1239,21 +1579,11 @@ CL_SendPureChecksums ================= */ void CL_SendPureChecksums( void ) { - const char *pChecksums; char cMsg[MAX_INFO_VALUE]; - int i; // if we are pure we need to send back a command with our referenced pk3 checksums - pChecksums = FS_ReferencedPakPureChecksums(); + Com_sprintf(cMsg, sizeof(cMsg), "cp %d %s", cl.serverId, FS_ReferencedPakPureChecksums()); - // "cp" - // "Yf" - Com_sprintf(cMsg, sizeof(cMsg), "Yf "); - Q_strcat(cMsg, sizeof(cMsg), va("%d ", cl.serverId) ); - Q_strcat(cMsg, sizeof(cMsg), pChecksums); - for (i = 0; i < 2; i++) { - cMsg[i] += 10; - } CL_AddReliableCommand( cMsg ); } @@ -1774,13 +2104,8 @@ void CL_MotdPacket( netadr_t from, const char *info ) { CL_InitServerInfo =================== */ -void CL_InitServerInfo( serverInfo_t *server, serverAddress_t *address ) { - server->adr.type = NA_IP; - server->adr.ip[0] = address->ip[0]; - server->adr.ip[1] = address->ip[1]; - server->adr.ip[2] = address->ip[2]; - server->adr.ip[3] = address->ip[3]; - server->adr.port = address->port; +void CL_InitServerInfo( serverInfo_t *server, netadr_t *address ) { + server->adr = *address; server->clients = 0; server->hostName[0] = '\0'; server->mapName[0] = '\0'; @@ -1801,8 +2126,8 @@ CL_ServersResponsePacket =================== */ void CL_ServersResponsePacket( netadr_t from, msg_t *msg ) { - int i, count, max, total; - serverAddress_t addresses[MAX_SERVERSPERPACKET]; + int i, count, total; + netadr_t addresses[MAX_SERVERSPERPACKET]; int numservers; byte* buffptr; byte* buffend; @@ -1815,71 +2140,66 @@ void CL_ServersResponsePacket( netadr_t from, msg_t *msg ) { cls.numGlobalServerAddresses = 0; } - if (cls.nummplayerservers == -1) { - cls.nummplayerservers = 0; - } - // parse through server response string numservers = 0; buffptr = msg->data; buffend = buffptr + msg->cursize; - while (buffptr+1 < buffend) { - // advance to initial token - do { - if (*buffptr++ == '\\') - break; - } - while (buffptr < buffend); - if ( buffptr >= buffend - 6 ) { + // advance to initial token + do + { + if(*buffptr == '\\' || *buffptr == '/') break; - } + + buffptr++; + } while (buffptr < buffend); - // parse out ip - addresses[numservers].ip[0] = *buffptr++; - addresses[numservers].ip[1] = *buffptr++; - addresses[numservers].ip[2] = *buffptr++; - addresses[numservers].ip[3] = *buffptr++; + while (buffptr + 1 < buffend) + { + if (*buffptr == '\\') + { + buffptr++; + + if (buffend - buffptr < sizeof(addresses[numservers].ip) + sizeof(addresses[numservers].port) + 1) + break; + for(i = 0; i < sizeof(addresses[numservers].ip); i++) + addresses[numservers].ip[i] = *buffptr++; + + addresses[numservers].type = NA_IP; + } + else + { + buffptr++; + + if (buffend - buffptr < sizeof(addresses[numservers].ip6) + sizeof(addresses[numservers].port) + 1) + break; + + for(i = 0; i < sizeof(addresses[numservers].ip6); i++) + addresses[numservers].ip6[i] = *buffptr++; + + addresses[numservers].type = NA_IP6; + } + // parse out port - addresses[numservers].port = (*buffptr++)<<8; + addresses[numservers].port = (*buffptr++) << 8; addresses[numservers].port += *buffptr++; addresses[numservers].port = BigShort( addresses[numservers].port ); // syntax check - if (*buffptr != '\\') { + if (*buffptr != '\\' && *buffptr != '/') break; - } - - Com_DPrintf( "server: %d ip: %d.%d.%d.%d:%d\n",numservers, - addresses[numservers].ip[0], - addresses[numservers].ip[1], - addresses[numservers].ip[2], - addresses[numservers].ip[3], - BigShort( addresses[numservers].port ) ); - + numservers++; - if (numservers >= MAX_SERVERSPERPACKET) { + if (numservers >= MAX_SERVERSPERPACKET) break; - } - - // parse out EOT - if (buffptr[1] == 'E' && buffptr[2] == 'O' && buffptr[3] == 'T') { - break; - } } - if (cls.masterNum == 0) { - count = cls.numglobalservers; - max = MAX_GLOBAL_SERVERS; - } else { - count = cls.nummplayerservers; - max = MAX_OTHER_SERVERS; - } + count = cls.numglobalservers; - for (i = 0; i < numservers && count < max; i++) { + for (i = 0; i < numservers && count < MAX_GLOBAL_SERVERS; i++) { // build net address - serverInfo_t *server = (cls.masterNum == 0) ? &cls.globalServers[count] : &cls.mplayerServers[count]; + serverInfo_t *server = &cls.globalServers[count]; CL_InitServerInfo( server, &addresses[i] ); // advance to next slot @@ -1887,29 +2207,18 @@ void CL_ServersResponsePacket( netadr_t from, msg_t *msg ) { } // if getting the global list - if (cls.masterNum == 0) { - if ( cls.numGlobalServerAddresses < MAX_GLOBAL_SERVERS ) { - // if we couldn't store the servers in the main list anymore - for (; i < numservers && count >= max; i++) { - serverAddress_t *addr; - // just store the addresses in an additional list - addr = &cls.globalServerAddresses[cls.numGlobalServerAddresses++]; - addr->ip[0] = addresses[i].ip[0]; - addr->ip[1] = addresses[i].ip[1]; - addr->ip[2] = addresses[i].ip[2]; - addr->ip[3] = addresses[i].ip[3]; - addr->port = addresses[i].port; - } + if ( count >= MAX_GLOBAL_SERVERS && cls.numGlobalServerAddresses < MAX_GLOBAL_SERVERS ) + { + // if we couldn't store the servers in the main list anymore + for (; i < numservers && cls.numGlobalServerAddresses < MAX_GLOBAL_SERVERS; i++) + { + // just store the addresses in an additional list + cls.globalServerAddresses[cls.numGlobalServerAddresses++] = addresses[i]; } } - if (cls.masterNum == 0) { - cls.numglobalservers = count; - total = count + cls.numGlobalServerAddresses; - } else { - cls.nummplayerservers = count; - total = count; - } + cls.numglobalservers = count; + total = count + cls.numGlobalServerAddresses; Com_Printf("%d servers parsed (total %d)\n", numservers, total); } @@ -1936,12 +2245,12 @@ void CL_ConnectionlessPacket( netadr_t from, msg_t *msg ) { Q_strncpyz( c, Cmd_Argv( 0 ), BIG_INFO_STRING ); Q_strncpyz( arg1, Cmd_Argv( 1 ), BIG_INFO_STRING ); - Com_DPrintf ("CL packet %s: %s\n", NET_AdrToString(from), c); + Com_DPrintf ("CL packet %s: %s\n", NET_AdrToStringwPort(from), c); // challenge from the server we are connecting to if ( !Q_stricmp(c, "challengeResponse") ) { if ( cls.state != CA_CONNECTING ) { - Com_Printf( "Unwanted challenge response received. Ignored.\n" ); + Com_DPrintf( "Unwanted challenge response received. Ignored.\n" ); } else { // start sending challenge repsonse instead of challenge request packets clc.challenge = atoi(arg1); @@ -1969,8 +2278,8 @@ void CL_ConnectionlessPacket( netadr_t from, msg_t *msg ) { } if ( !NET_CompareBaseAdr( from, clc.serverAddress ) ) { Com_Printf( "connectResponse from a different address. Ignored.\n" ); - Com_Printf( "%s should have been %s\n", NET_AdrToString( from ), - NET_AdrToString( clc.serverAddress ) ); + Com_Printf( "%s should have been %s\n", NET_AdrToStringwPort( from ), + NET_AdrToStringwPort( clc.serverAddress ) ); return; } Netchan_Setup (NS_CLIENT, &clc.netchan, from, Cvar_VariableValue( "net_qport" ) ); @@ -2055,7 +2364,7 @@ void CL_PacketEvent( netadr_t from, msg_t *msg ) { } if ( msg->cursize < 4 ) { - Com_Printf ("%s: Runt packet\n",NET_AdrToString( from )); + Com_Printf ("%s: Runt packet\n", NET_AdrToStringwPort( from )); return; } @@ -2064,7 +2373,7 @@ void CL_PacketEvent( netadr_t from, msg_t *msg ) { // if ( !NET_CompareAdr( from, clc.netchan.remoteAddress ) ) { Com_DPrintf ("%s:sequenced packet without connection\n" - ,NET_AdrToString( from ) ); + , NET_AdrToStringwPort( from ) ); // FIXME: send a client disconnect? return; } @@ -2190,7 +2499,7 @@ void CL_Frame ( int msec ) { #endif if ( cls.state == CA_DISCONNECTED && !( Key_GetCatcher( ) & KEYCATCH_UI ) - && !com_sv_running->integer ) { + && !com_sv_running->integer && uivm ) { // if disconnected, bring up the menu S_StopAllSounds(); VM_Call( uivm, UI_SET_ACTIVE_MENU, UIMENU_MAIN ); @@ -2282,6 +2591,14 @@ void CL_Frame ( int msec ) { // update audio S_Update(); +#ifdef USE_VOIP + CL_CaptureVoip(); +#endif + +#ifdef USE_MUMBLE + CL_UpdateMumble(); +#endif + // advance local effects for next frame SCR_RunCinematic(); @@ -2385,6 +2702,10 @@ void CL_StartHunkUsers( qboolean rendererOnly ) { S_BeginRegistration(); } + if( com_dedicated->integer ) { + return; + } + if ( !cls.uiStarted ) { cls.uiStarted = qtrue; CL_InitUI(); @@ -2442,6 +2763,7 @@ void CL_InitRef( void ) { ri.FS_FileExists = FS_FileExists; ri.Cvar_Get = Cvar_Get; ri.Cvar_Set = Cvar_Set; + ri.Cvar_CheckRange = Cvar_CheckRange; // cinematic stuff @@ -2608,7 +2930,7 @@ CL_Init void CL_Init( void ) { Com_Printf( "----- Client Initialization -----\n" ); - Con_Init (); + Con_Init (); CL_ClearState (); @@ -2626,7 +2948,6 @@ void CL_Init( void ) { cl_timeout = Cvar_Get ("cl_timeout", "200", 0); - cl_master = Cvar_Get ("cl_master", MASTER_SERVER_NAME, CVAR_ARCHIVE); cl_timeNudge = Cvar_Get ("cl_timeNudge", "0", CVAR_TEMP ); cl_shownet = Cvar_Get ("cl_shownet", "0", CVAR_TEMP ); cl_showSend = Cvar_Get ("cl_showSend", "0", CVAR_TEMP ); @@ -2666,7 +2987,7 @@ void CL_Init( void ) { cl_conXOffset = Cvar_Get ("cl_conXOffset", "0", 0); #ifdef MACOS_X - // In game video is REALLY slow in Mac OS X right now due to driver slowness + // In game video is REALLY slow in Mac OS X right now due to driver slowness cl_inGameVideo = Cvar_Get ("r_inGameVideo", "0", CVAR_ARCHIVE); #else cl_inGameVideo = Cvar_Get ("r_inGameVideo", "1", CVAR_ARCHIVE); @@ -2683,7 +3004,7 @@ void CL_Init( void ) { m_forward = Cvar_Get ("m_forward", "0.25", CVAR_ARCHIVE); m_side = Cvar_Get ("m_side", "0.25", CVAR_ARCHIVE); #ifdef MACOS_X - // Input is jittery on OS X w/o this + // Input is jittery on OS X w/o this m_filter = Cvar_Get ("m_filter", "1", CVAR_ARCHIVE); #else m_filter = Cvar_Get ("m_filter", "0", CVAR_ARCHIVE); @@ -2709,9 +3030,42 @@ void CL_Init( void ) { Cvar_Get ("password", "", CVAR_USERINFO); +#ifdef USE_MUMBLE + cl_useMumble = Cvar_Get ("cl_useMumble", "0", CVAR_ARCHIVE | CVAR_LATCH); + cl_mumbleScale = Cvar_Get ("cl_mumbleScale", "0.0254", CVAR_ARCHIVE); +#endif + +#ifdef USE_VOIP + cl_voipSend = Cvar_Get ("cl_voipSend", "0", 0); + cl_voipSendTarget = Cvar_Get ("cl_voipSendTarget", "all", 0); + cl_voipGainDuringCapture = Cvar_Get ("cl_voipGainDuringCapture", "0.2", CVAR_ARCHIVE); + cl_voipCaptureMult = Cvar_Get ("cl_voipCaptureMult", "2.0", CVAR_ARCHIVE); + cl_voipUseVAD = Cvar_Get ("cl_voipUseVAD", "0", CVAR_ARCHIVE); + cl_voipVADThreshold = Cvar_Get ("cl_voipVADThreshold", "0.25", CVAR_ARCHIVE); + cl_voipShowMeter = Cvar_Get ("cl_voipShowMeter", "1", CVAR_ARCHIVE); + + // This is a protocol version number. + cl_voip = Cvar_Get ("cl_voip", "1", CVAR_USERINFO | CVAR_ARCHIVE | CVAR_LATCH); + Cvar_CheckRange( cl_voip, 0, 1, qtrue ); + + // If your data rate is too low, you'll get Connection Interrupted warnings + // when VoIP packets arrive, even if you have a broadband connection. + // This might work on rates lower than 25000, but for safety's sake, we'll + // just demand it. Who doesn't have at least a DSL line now, anyhow? If + // you don't, you don't need VoIP. :) + if ((cl_voip->integer) && (Cvar_VariableIntegerValue("rate") < 25000)) { + Com_Printf("Your network rate is too slow for VoIP.\n"); + Com_Printf("Set 'Data Rate' to 'LAN/Cable/xDSL' in 'Setup/System/Network' and restart.\n"); + Com_Printf("Until then, VoIP is disabled.\n"); + Cvar_Set("cl_voip", "0"); + } +#endif + // cgame might not be initialized before menu is used Cvar_Get ("cg_viewsize", "100", CVAR_ARCHIVE ); + // Make sure cg_stereoSeparation is zero as that variable is deprecated and should not be used anymore. + Cvar_Get ("cg_stereoSeparation", "0", CVAR_ROM); // // register our commands @@ -2744,11 +3098,11 @@ void CL_Init( void ) { SCR_Init (); - Cbuf_Execute (); +// Cbuf_Execute (); Cvar_Set( "cl_running", "1" ); - CL_GenerateQKey(); + CL_GenerateQKey(); Cvar_Get( "cl_guid", "", CVAR_USERINFO | CVAR_ROM ); CL_UpdateGUID( NULL, 0 ); @@ -2843,12 +3197,6 @@ static void CL_SetServerInfoByAddress(netadr_t from, const char *info, int ping) } } - for (i = 0; i < MAX_OTHER_SERVERS; i++) { - if (NET_CompareAdr(from, cls.mplayerServers[i].adr)) { - CL_SetServerInfo(&cls.mplayerServers[i], info, ping); - } - } - for (i = 0; i < MAX_GLOBAL_SERVERS; i++) { if (NET_CompareAdr(from, cls.globalServers[i].adr)) { CL_SetServerInfo(&cls.globalServers[i], info, ping); @@ -2871,7 +3219,6 @@ CL_ServerInfoPacket void CL_ServerInfoPacket( netadr_t from, msg_t *msg ) { int i, type; char info[MAX_INFO_STRING]; - char* str; char *infoString; int prot; @@ -2902,12 +3249,12 @@ void CL_ServerInfoPacket( netadr_t from, msg_t *msg ) { { case NA_BROADCAST: case NA_IP: - str = "udp"; type = 1; break; - + case NA_IP6: + type = 2; + break; default: - str = "???"; type = 0; break; } @@ -2959,7 +3306,7 @@ void CL_ServerInfoPacket( netadr_t from, msg_t *msg ) { if (info[strlen(info)-1] != '\n') { strncat(info, "\n", sizeof(info) - 1); } - Com_Printf( "%s: %s", NET_AdrToString( from ), info ); + Com_Printf( "%s: %s", NET_AdrToStringwPort( from ), info ); } } @@ -3017,7 +3364,7 @@ int CL_ServerStatus( char *serverAddress, char *serverStatusString, int maxLen ) return qfalse; } // get the address - if ( !NET_StringToAdr( serverAddress, &to ) ) { + if ( !NET_StringToAdr( serverAddress, &to, NA_UNSPEC) ) { return qfalse; } serverStatus = CL_GetServerStatus( to ); @@ -3192,6 +3539,8 @@ void CL_LocalServers_f( void ) { to.type = NA_BROADCAST; NET_SendPacket( NS_CLIENT, strlen( message ), message, to ); + to.type = NA_MULTICAST6; + NET_SendPacket( NS_CLIENT, strlen( message ), message, to ); } } } @@ -3203,43 +3552,49 @@ CL_GlobalServers_f */ void CL_GlobalServers_f( void ) { netadr_t to; - int i; - int count; - char *buffptr; - char command[1024]; + int count, i, masterNum; + char command[1024], *masteraddress; - if ( Cmd_Argc() < 3) { - Com_Printf( "usage: globalservers <master# 0-1> <protocol> [keywords]\n"); + if ((count = Cmd_Argc()) < 3 || (masterNum = atoi(Cmd_Argv(1))) < 0 || masterNum > 4) + { + Com_Printf( "usage: globalservers <master# 0-4> <protocol> [keywords]\n"); return; } - cls.masterNum = atoi( Cmd_Argv(1) ); - - Com_Printf( "Requesting servers from the master...\n"); + sprintf(command, "sv_master%d", masterNum + 1); + masteraddress = Cvar_VariableString(command); + + if(!*masteraddress) + { + Com_Printf( "CL_GlobalServers_f: Error: No master server address given.\n"); + return; + } // reset the list, waiting for response // -1 is used to distinguish a "no response" - NET_StringToAdr( cl_master->string, &to ); - - if( cls.masterNum == 1 ) { - cls.nummplayerservers = -1; - cls.pingUpdateSource = AS_MPLAYER; - } - else { - cls.numglobalservers = -1; - cls.pingUpdateSource = AS_GLOBAL; + i = NET_StringToAdr(masteraddress, &to, NA_UNSPEC); + + if(!i) + { + Com_Printf( "CL_GlobalServers_f: Error: could not resolve address of master %s\n", masteraddress); + return; } - to.type = NA_IP; - to.port = BigShort(PORT_MASTER); + else if(i == 2) + to.port = BigShort(PORT_MASTER); + + Com_Printf("Requesting servers from master %s...\n", masteraddress); - sprintf( command, "getservers %s", Cmd_Argv(2) ); + cls.numglobalservers = -1; + cls.pingUpdateSource = AS_GLOBAL; - // tack on keywords - buffptr = command + strlen( command ); - count = Cmd_Argc(); - for (i=3; i<count; i++) - buffptr += sprintf( buffptr, " %s", Cmd_Argv(i) ); + Com_sprintf( command, sizeof(command), "getservers %s", Cmd_Argv(2) ); + + for (i=3; i < count; i++) + { + Q_strcat(command, sizeof(command), " "); + Q_strcat(command, sizeof(command), Cmd_Argv(i)); + } NET_OutOfBandPrint( NS_SERVER, to, "%s", command ); } @@ -3264,7 +3619,7 @@ void CL_GetPing( int n, char *buf, int buflen, int *pingtime ) return; } - str = NET_AdrToString( cl_pinglist[n].adr ); + str = NET_AdrToStringwPort( cl_pinglist[n].adr ); Q_strncpyz( buf, str, buflen ); time = cl_pinglist[n].time; @@ -3423,17 +3778,33 @@ void CL_Ping_f( void ) { netadr_t to; ping_t* pingptr; char* server; + int argc; + netadrtype_t family = NA_UNSPEC; + + argc = Cmd_Argc(); - if ( Cmd_Argc() != 2 ) { - Com_Printf( "usage: ping [server]\n"); + if ( argc != 2 && argc != 3 ) { + Com_Printf( "usage: ping [-4|-6] server\n"); return; } + + if(argc == 2) + server = Cmd_Argv(1); + else + { + if(!strcmp(Cmd_Argv(1), "-4")) + family = NA_IP; + else if(!strcmp(Cmd_Argv(1), "-6")) + family = NA_IP6; + else + Com_Printf( "warning: only -4 or -6 as address type understood.\n"); + + server = Cmd_Argv(2); + } Com_Memset( &to, 0, sizeof(netadr_t) ); - server = Cmd_Argv(1); - - if ( !NET_StringToAdr( server, &to ) ) { + if ( !NET_StringToAdr( server, &to, family ) ) { return; } @@ -3476,10 +3847,6 @@ qboolean CL_UpdateVisiblePings_f(int source) { server = &cls.localServers[0]; max = cls.numlocalservers; break; - case AS_MPLAYER : - server = &cls.mplayerServers[0]; - max = cls.nummplayerservers; - break; case AS_GLOBAL : server = &cls.globalServers[0]; max = cls.numglobalservers; @@ -3488,6 +3855,8 @@ qboolean CL_UpdateVisiblePings_f(int source) { server = &cls.favoriteServers[0]; max = cls.numfavoriteservers; break; + default: + return qfalse; } for (i = 0; i < max; i++) { if (server[i].visible) { @@ -3561,32 +3930,53 @@ CL_ServerStatus_f ================== */ void CL_ServerStatus_f(void) { - netadr_t to; + netadr_t to, *toptr = NULL; char *server; serverStatus_t *serverStatus; + int argc; + netadrtype_t family = NA_UNSPEC; - Com_Memset( &to, 0, sizeof(netadr_t) ); + argc = Cmd_Argc(); - if ( Cmd_Argc() != 2 ) { - if ( cls.state != CA_ACTIVE || clc.demoplaying ) { + if ( argc != 2 && argc != 3 ) + { + if (cls.state != CA_ACTIVE || clc.demoplaying) + { Com_Printf ("Not connected to a server.\n"); - Com_Printf( "Usage: serverstatus [server]\n"); - return; + Com_Printf( "usage: serverstatus [-4|-6] server\n"); + return; } - server = cls.servername; - } - else { - server = Cmd_Argv(1); + + toptr = &clc.serverAddress; } + + if(!toptr) + { + Com_Memset( &to, 0, sizeof(netadr_t) ); + + if(argc == 2) + server = Cmd_Argv(1); + else + { + if(!strcmp(Cmd_Argv(1), "-4")) + family = NA_IP; + else if(!strcmp(Cmd_Argv(1), "-6")) + family = NA_IP6; + else + Com_Printf( "warning: only -4 or -6 as address type understood.\n"); + + server = Cmd_Argv(2); + } - if ( !NET_StringToAdr( server, &to ) ) { - return; + toptr = &to; + if ( !NET_StringToAdr( server, toptr, family ) ) + return; } - NET_OutOfBandPrint( NS_CLIENT, to, "getstatus" ); + NET_OutOfBandPrint( NS_CLIENT, *toptr, "getstatus" ); - serverStatus = CL_GetServerStatus( to ); - serverStatus->address = to; + serverStatus = CL_GetServerStatus( *toptr ); + serverStatus->address = *toptr; serverStatus->print = qtrue; serverStatus->pending = qtrue; } |