summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorTim Angus <tim@ngus.net>2009-10-13 17:17:27 +0000
committerTim Angus <tim@ngus.net>2013-01-03 00:16:49 +0000
commit6efd4cef3cfcc44d6727cb0e54da26fbb74a7533 (patch)
treefdb5ee764999ac868d00c54cefb8c290f1735fd6 /src
parentfafe107646105e680e2bd4a82d9330dffaf69c9a (diff)
* Merge ioq3-r1666
Diffstat (limited to 'src')
-rw-r--r--src/cgame/cg_main.c1
-rw-r--r--src/client/cl_cgame.c2
-rw-r--r--src/client/cl_curl.c2
-rw-r--r--src/client/cl_input.c2
-rw-r--r--src/client/cl_keys.c239
-rw-r--r--src/client/cl_main.c85
-rw-r--r--src/client/cl_parse.c6
-rw-r--r--src/client/client.h2
-rw-r--r--src/client/snd_dma.c8
-rw-r--r--src/client/snd_openal.c27
-rw-r--r--src/qcommon/common.c82
-rw-r--r--src/qcommon/files.c13
-rw-r--r--src/qcommon/msg.c23
-rw-r--r--src/qcommon/q_shared.h18
-rw-r--r--src/qcommon/qcommon.h2
-rw-r--r--src/qcommon/vm_x86_64_assembler.c2
-rw-r--r--src/server/server.h1
-rw-r--r--src/server/sv_client.c53
18 files changed, 283 insertions, 285 deletions
diff --git a/src/cgame/cg_main.c b/src/cgame/cg_main.c
index da607deb..89082cee 100644
--- a/src/cgame/cg_main.c
+++ b/src/cgame/cg_main.c
@@ -1894,3 +1894,4 @@ static char *CG_VoIPString( void )
return voipString;
}
+
diff --git a/src/client/cl_cgame.c b/src/client/cl_cgame.c
index 8bf10f6d..ef61834c 100644
--- a/src/client/cl_cgame.c
+++ b/src/client/cl_cgame.c
@@ -469,7 +469,7 @@ intptr_t CL_CgameSystemCalls( intptr_t *args ) {
Cmd_RemoveCommand( VMA(1) );
return 0;
case CG_SENDCLIENTCOMMAND:
- CL_AddReliableCommand( VMA(1) );
+ CL_AddReliableCommand(VMA(1), qfalse);
return 0;
case CG_UPDATESCREEN:
// this is used during lengthy level loading, so pump message loop
diff --git a/src/client/cl_curl.c b/src/client/cl_curl.c
index 4c34667c..10d09bd5 100644
--- a/src/client/cl_curl.c
+++ b/src/client/cl_curl.c
@@ -292,7 +292,7 @@ void CL_cURL_BeginDownload( const char *localName, const char *remoteURL )
if(!(clc.sv_allowDownload & DLF_NO_DISCONNECT) &&
!clc.cURLDisconnected) {
- CL_AddReliableCommand("disconnect");
+ CL_AddReliableCommand("disconnect", qtrue);
CL_WritePacket();
CL_WritePacket();
CL_WritePacket();
diff --git a/src/client/cl_input.c b/src/client/cl_input.c
index d3c38868..49551662 100644
--- a/src/client/cl_input.c
+++ b/src/client/cl_input.c
@@ -824,7 +824,7 @@ void CL_WritePacket( void ) {
// also use the message acknowledge
key ^= clc.serverMessageSequence;
// also use the last acknowledged server command in the key
- key ^= Com_HashKey(clc.serverCommands[ clc.serverCommandSequence & (MAX_RELIABLE_COMMANDS-1) ], 32);
+ key ^= MSG_HashKey(clc.serverCommands[ clc.serverCommandSequence & (MAX_RELIABLE_COMMANDS-1) ], 32);
// write all the commands, including the predicted command
for ( i = 0 ; i < count ; i++ ) {
diff --git a/src/client/cl_keys.c b/src/client/cl_keys.c
index 10abefc2..4c36485b 100644
--- a/src/client/cl_keys.c
+++ b/src/client/cl_keys.c
@@ -1070,94 +1070,72 @@ void CL_InitKeyCommands( void ) {
/*
===================
-CL_AddKeyUpCommands
+CL_ParseBinding
+
+Execute the commands in the bind string
===================
*/
-void CL_AddKeyUpCommands( int key, char *kb, unsigned time) {
- int i;
- char button[1024], *buttonPtr;
- char cmd[1024];
- qboolean keyevent;
+void CL_ParseBinding( int key, qboolean down, unsigned time )
+{
+ char buf[ MAX_STRING_CHARS ], *p = buf, *end;
- if ( !kb ) {
+ if( !keys[key].binding || !keys[key].binding[0] )
return;
- }
- keyevent = qfalse;
- buttonPtr = button;
- for ( i = 0; ; i++ ) {
- if ( kb[i] == ';' || !kb[i] ) {
- *buttonPtr = '\0';
- if ( button[0] == '+') {
- // button commands add keynum and time as parms so that multiple
- // sources can be discriminated and subframe corrected
- Com_sprintf (cmd, sizeof(cmd), "-%s %i %i\n", button+1, key, time);
- Cbuf_AddText (cmd);
- keyevent = qtrue;
- } else {
- if (keyevent) {
- // down-only command
- Cbuf_AddText (button);
- Cbuf_AddText ("\n");
- }
- }
- buttonPtr = button;
- while ( (kb[i] <= ' ' || kb[i] == ';') && kb[i] != 0 ) {
- i++;
- }
+ Q_strncpyz( buf, keys[key].binding, sizeof( buf ) );
+
+ while( 1 )
+ {
+ while( isspace( *p ) )
+ p++;
+ end = strchr( p, ';' );
+ if( end )
+ *end = '\0';
+ if( *p == '+' )
+ {
+ // button commands add keynum and time as parameters
+ // so that multiple sources can be discriminated and
+ // subframe corrected
+ char cmd[1024];
+ Com_sprintf( cmd, sizeof( cmd ), "%c%s %d %d\n",
+ ( down ) ? '+' : '-', p + 1, key, time );
+ Cbuf_AddText( cmd );
}
- *buttonPtr++ = kb[i];
- if ( !kb[i] ) {
- break;
+ else if( down )
+ {
+ // normal commands only execute on key press
+ Cbuf_AddText( p );
+ Cbuf_AddText( "\n" );
}
+ if( !end )
+ break;
+ p = end + 1;
}
}
/*
===================
-CL_KeyEvent
+CL_KeyDownEvent
-Called by the system for both key up and key down events
+Called by CL_KeyEvent to handle a keypress
===================
*/
-void CL_KeyEvent (int key, qboolean down, unsigned time) {
- char *kb;
- char cmd[1024];
-
- // update auto-repeat status and BUTTON_ANY status
- keys[key].down = down;
-
- if (down) {
- keys[key].repeats++;
- if ( keys[key].repeats == 1) {
- anykeydown++;
- }
- } else {
- keys[key].repeats = 0;
- anykeydown--;
- if (anykeydown < 0) {
- anykeydown = 0;
- }
- }
+void CL_KeyDownEvent( int key, unsigned time )
+{
+ keys[key].down = qtrue;
+ keys[key].repeats++;
+ if( keys[key].repeats == 1 )
+ anykeydown++;
- if (key == K_ENTER)
+ if( keys[K_ALT].down && key == K_ENTER )
{
- if (down)
- {
- if (keys[K_ALT].down)
- {
- Cvar_SetValue( "r_fullscreen",
- !Cvar_VariableIntegerValue( "r_fullscreen" ) );
- return;
- }
- }
+ Cvar_SetValue( "r_fullscreen",
+ !Cvar_VariableIntegerValue( "r_fullscreen" ) );
+ return;
}
// console key is hardcoded, so the user can never unbind it
- if (key == K_CONSOLE ||
- ( key == K_ESCAPE && keys[K_SHIFT].down ) ) {
- if (!down) {
- return;
- }
+ if( key == K_CONSOLE || ( keys[K_SHIFT].down && key == K_ESCAPE ) )
+ {
Con_ToggleConsole_f ();
Key_ClearStates ();
return;
@@ -1165,7 +1143,7 @@ void CL_KeyEvent (int key, qboolean down, unsigned time) {
// keys can still be used for bound actions
- if ( down && ( key < 128 || key == K_MOUSE1 ) &&
+ if ( ( key < 128 || key == K_MOUSE1 ) &&
( clc.demoplaying || cls.state == CA_CINEMATIC ) && Key_GetCatcher( ) == 0 ) {
if (Cvar_VariableValue ("com_cameraMode") == 0) {
@@ -1174,9 +1152,8 @@ void CL_KeyEvent (int key, qboolean down, unsigned time) {
}
}
-
// escape is always handled special
- if ( key == K_ESCAPE && down ) {
+ if ( key == K_ESCAPE ) {
// escape always gets out of CGAME stuff
if (Key_GetCatcher( ) & KEYCATCH_CGAME) {
Key_SetCatcher( Key_GetCatcher( ) & ~KEYCATCH_CGAME );
@@ -1196,89 +1173,79 @@ void CL_KeyEvent (int key, qboolean down, unsigned time) {
return;
}
- VM_Call( uivm, UI_KEY_EVENT, key, down );
+ VM_Call( uivm, UI_KEY_EVENT, key, qtrue );
return;
}
- //
- // key up events only perform actions if the game key binding is
- // a button command (leading + sign). These will be processed even in
- // console mode and menu mode, to keep the character from continuing
- // an action started before a mode switch.
- //
- if (!down ) {
- if ( cls.state != CA_DISCONNECTED ) {
- kb = keys[key].binding;
-
- CL_AddKeyUpCommands( key, kb, time );
- }
-
- if ( Key_GetCatcher( ) & KEYCATCH_UI && uivm ) {
- VM_Call( uivm, UI_KEY_EVENT, key, down );
- } else if ( Key_GetCatcher( ) & KEYCATCH_CGAME && cgvm ) {
- VM_Call( cgvm, CG_KEY_EVENT, key, down );
- }
-
- return;
- }
-
-
// distribute the key down event to the apropriate handler
if ( Key_GetCatcher( ) & KEYCATCH_CONSOLE ) {
Console_Key( key );
} else if ( Key_GetCatcher( ) & KEYCATCH_UI ) {
if ( uivm ) {
- VM_Call( uivm, UI_KEY_EVENT, key, down );
+ VM_Call( uivm, UI_KEY_EVENT, key, qtrue );
}
} else if ( Key_GetCatcher( ) & KEYCATCH_CGAME ) {
if ( cgvm ) {
- VM_Call( cgvm, CG_KEY_EVENT, key, down );
+ VM_Call( cgvm, CG_KEY_EVENT, key, qtrue );
}
} else if ( cls.state == CA_DISCONNECTED ) {
Console_Key( key );
} else {
// send the bound action
- kb = keys[key].binding;
- if ( !kb ) {
- if (key >= 200) {
- Com_Printf ("%s is unbound, use controls menu to set.\n"
- , Key_KeynumToString( key ) );
- }
- } else if (kb[0] == '+') {
- int i;
- char button[1024], *buttonPtr;
- buttonPtr = button;
- for ( i = 0; ; i++ ) {
- if ( kb[i] == ';' || !kb[i] ) {
- *buttonPtr = '\0';
- if ( button[0] == '+') {
- // button commands add keynum and time as parms so that multiple
- // sources can be discriminated and subframe corrected
- Com_sprintf (cmd, sizeof(cmd), "%s %i %i\n", button, key, time);
- Cbuf_AddText (cmd);
- } else {
- // down-only command
- Cbuf_AddText (button);
- Cbuf_AddText ("\n");
- }
- buttonPtr = button;
- while ( (kb[i] <= ' ' || kb[i] == ';') && kb[i] != 0 ) {
- i++;
- }
- }
- *buttonPtr++ = kb[i];
- if ( !kb[i] ) {
- break;
- }
- }
- } else {
- // down-only command
- Cbuf_AddText (kb);
- Cbuf_AddText ("\n");
- }
+ CL_ParseBinding( key, qtrue, time );
+ }
+ return;
+}
+
+/*
+===================
+CL_KeyUpEvent
+
+Called by CL_KeyEvent to handle a keyrelease
+===================
+*/
+void CL_KeyUpEvent( int key, unsigned time )
+{
+ keys[key].repeats = 0;
+ keys[key].down = qfalse;
+ anykeydown--;
+ if (anykeydown < 0) {
+ anykeydown = 0;
+ }
+
+ // don't process key-up events for the console key
+ if ( key == K_CONSOLE || ( key == K_ESCAPE && keys[K_SHIFT].down ) )
+ return;
+
+ //
+ // key up events only perform actions if the game key binding is
+ // a button command (leading + sign). These will be processed even in
+ // console mode and menu mode, to keep the character from continuing
+ // an action started before a mode switch.
+ //
+ if( cls.state != CA_DISCONNECTED )
+ CL_ParseBinding( key, qfalse, time );
+
+ if ( Key_GetCatcher( ) & KEYCATCH_UI && uivm ) {
+ VM_Call( uivm, UI_KEY_EVENT, key, qfalse );
+ } else if ( Key_GetCatcher( ) & KEYCATCH_CGAME && cgvm ) {
+ VM_Call( cgvm, CG_KEY_EVENT, key, qfalse );
}
}
+/*
+===================
+CL_KeyEvent
+
+Called by the system for both key up and key down events
+===================
+*/
+void CL_KeyEvent (int key, qboolean down, unsigned time) {
+ if( down )
+ CL_KeyDownEvent( key, time );
+ else
+ CL_KeyUpEvent( key, time );
+}
/*
===================
diff --git a/src/client/cl_main.c b/src/client/cl_main.c
index 0aafa529..a8b59c27 100644
--- a/src/client/cl_main.c
+++ b/src/client/cl_main.c
@@ -191,7 +191,7 @@ void CL_UpdateVoipIgnore(const char *idstr, qboolean ignore)
if ((id >= 0) && (id < MAX_CLIENTS)) {
clc.voipIgnore[id] = ignore;
CL_AddReliableCommand(va("voip %s %d",
- ignore ? "ignore" : "unignore", id));
+ ignore ? "ignore" : "unignore", id), qfalse);
Com_Printf("VoIP: %s ignoring player #%d\n",
ignore ? "Now" : "No longer", id);
return;
@@ -303,11 +303,11 @@ void CL_Voip_f( void )
}
} else if (strcmp(cmd, "muteall") == 0) {
Com_Printf("VoIP: muting incoming voice\n");
- CL_AddReliableCommand("voip muteall");
+ CL_AddReliableCommand("voip muteall", qfalse);
clc.voipMuteAll = qtrue;
} else if (strcmp(cmd, "unmuteall") == 0) {
Com_Printf("VoIP: unmuting incoming voice\n");
- CL_AddReliableCommand("voip unmuteall");
+ CL_AddReliableCommand("voip unmuteall", qfalse);
clc.voipMuteAll = qfalse;
} else {
Com_Printf("usage: voip [un]ignore <playerID#>\n"
@@ -510,17 +510,25 @@ The given command will be transmitted to the server, and is gauranteed to
not have future usercmd_t executed before it is executed
======================
*/
-void CL_AddReliableCommand( const char *cmd ) {
- int index;
-
+void CL_AddReliableCommand(const char *cmd, qboolean isDisconnectCmd)
+{
+ int unacknowledged = clc.reliableSequence - clc.reliableAcknowledge;
+
// if we would be losing an old command that hasn't been acknowledged,
// we must drop the connection
- if ( clc.reliableSequence - clc.reliableAcknowledge > MAX_RELIABLE_COMMANDS ) {
- Com_Error( ERR_DROP, "Client command overflow" );
+ // also leave one slot open for the disconnect command in this case.
+
+ if ((isDisconnectCmd && unacknowledged > MAX_RELIABLE_COMMANDS) ||
+ (!isDisconnectCmd && unacknowledged >= MAX_RELIABLE_COMMANDS))
+ {
+ if(com_errorEntered)
+ return;
+ else
+ Com_Error(ERR_DROP, "Client command overflow");
}
- clc.reliableSequence++;
- index = clc.reliableSequence & ( MAX_RELIABLE_COMMANDS - 1 );
- Q_strncpyz( clc.reliableCommands[ index ], cmd, sizeof( clc.reliableCommands[ index ] ) );
+
+ Q_strncpyz(clc.reliableCommands[++clc.reliableSequence & (MAX_RELIABLE_COMMANDS - 1)],
+ cmd, sizeof(*clc.reliableCommands));
}
/*
@@ -1329,7 +1337,7 @@ void CL_Disconnect( qboolean showMainMenu ) {
// send a disconnect message to the server
// send it a few times in case one is dropped
if ( cls.state >= CA_CONNECTED ) {
- CL_AddReliableCommand( "disconnect" );
+ CL_AddReliableCommand("disconnect", qtrue);
CL_WritePacket();
CL_WritePacket();
CL_WritePacket();
@@ -1388,9 +1396,9 @@ void CL_ForwardCommandToServer( const char *string ) {
}
if ( Cmd_Argc() > 1 ) {
- CL_AddReliableCommand( string );
+ CL_AddReliableCommand(string, qfalse);
} else {
- CL_AddReliableCommand( cmd );
+ CL_AddReliableCommand(cmd, qfalse);
}
}
@@ -1457,45 +1465,10 @@ void CL_ForwardToServer_f( void ) {
// don't forward the first argument
if ( Cmd_Argc() > 1 ) {
- CL_AddReliableCommand( Cmd_Args() );
- }
-}
-
-/*
-==================
-CL_Setenv_f
-
-Mostly for controlling voodoo environment variables
-==================
-*/
-void CL_Setenv_f( void ) {
- int argc = Cmd_Argc();
-
- if ( argc > 2 ) {
- char buffer[1024];
- int i;
-
- strcpy( buffer, Cmd_Argv(1) );
- strcat( buffer, "=" );
-
- for ( i = 2; i < argc; i++ ) {
- strcat( buffer, Cmd_Argv( i ) );
- strcat( buffer, " " );
- }
-
- putenv( buffer );
- } else if ( argc == 2 ) {
- char *env = getenv( Cmd_Argv(1) );
-
- if ( env ) {
- Com_Printf( "%s=%s\n", Cmd_Argv(1), env );
- } else {
- Com_Printf( "%s undefined\n", Cmd_Argv(1));
- }
+ CL_AddReliableCommand(Cmd_Args(), qfalse);
}
}
-
/*
==================
CL_Disconnect_f
@@ -1697,7 +1670,7 @@ void CL_SendPureChecksums( void ) {
// if we are pure we need to send back a command with our referenced pk3 checksums
Com_sprintf(cMsg, sizeof(cMsg), "cp %d %s", cl.serverId, FS_ReferencedPakPureChecksums());
- CL_AddReliableCommand( cMsg );
+ CL_AddReliableCommand(cMsg, qfalse);
}
/*
@@ -1706,7 +1679,7 @@ CL_ResetPureClientAtServer
=================
*/
void CL_ResetPureClientAtServer( void ) {
- CL_AddReliableCommand( va("vdr") );
+ CL_AddReliableCommand("vdr", qfalse);
}
/*
@@ -1888,7 +1861,7 @@ void CL_DownloadsComplete( void ) {
FS_Restart(clc.checksumFeed); // We possibly downloaded a pak, restart the file system to load it
// inform the server so we get new gamestate info
- CL_AddReliableCommand( "donedl" );
+ CL_AddReliableCommand("donedl", qfalse);
// by sending the donedl command we request a new gamestate
// so we don't want to load stuff yet
@@ -1958,7 +1931,7 @@ void CL_BeginDownload( const char *localName, const char *remoteName ) {
// Stop any errant looping sounds that may be playing
S_ClearLoopingSounds( qtrue );
- CL_AddReliableCommand( va("download %s", remoteName) );
+ CL_AddReliableCommand( va("download %s", remoteName), qfalse );
}
/*
@@ -2809,7 +2782,7 @@ void CL_CheckUserinfo( void ) {
if(cvar_modifiedFlags & CVAR_USERINFO)
{
cvar_modifiedFlags &= ~CVAR_USERINFO;
- CL_AddReliableCommand( va("userinfo \"%s\"", Cvar_InfoString( CVAR_USERINFO ) ) );
+ CL_AddReliableCommand(va("userinfo \"%s\"", Cvar_InfoString( CVAR_USERINFO ) ), qfalse);
}
}
@@ -3455,7 +3428,6 @@ void CL_Init( void ) {
Cmd_AddCommand ("globalservers", CL_GlobalServers_f);
Cmd_AddCommand ("rcon", CL_Rcon_f);
Cmd_SetCommandCompletionFunc( "rcon", CL_CompleteRcon );
- Cmd_AddCommand ("setenv", CL_Setenv_f );
Cmd_AddCommand ("ping", CL_Ping_f );
Cmd_AddCommand ("serverstatus", CL_ServerStatus_f );
Cmd_AddCommand ("showip", CL_ShowIP_f );
@@ -3522,7 +3494,6 @@ void CL_Shutdown( void ) {
Cmd_RemoveCommand ("localservers");
Cmd_RemoveCommand ("globalservers");
Cmd_RemoveCommand ("rcon");
- Cmd_RemoveCommand ("setenv");
Cmd_RemoveCommand ("ping");
Cmd_RemoveCommand ("serverstatus");
Cmd_RemoveCommand ("showip");
diff --git a/src/client/cl_parse.c b/src/client/cl_parse.c
index 96d4f799..08fab5a9 100644
--- a/src/client/cl_parse.c
+++ b/src/client/cl_parse.c
@@ -553,7 +553,7 @@ void CL_ParseDownload ( msg_t *msg ) {
if (!*clc.downloadTempName) {
Com_Printf("Server sending download, but no download was requested\n");
- CL_AddReliableCommand( "stopdl" );
+ CL_AddReliableCommand("stopdl", qfalse);
return;
}
@@ -595,7 +595,7 @@ void CL_ParseDownload ( msg_t *msg ) {
if (!clc.download) {
Com_Printf( "Could not create %s\n", clc.downloadTempName );
- CL_AddReliableCommand( "stopdl" );
+ CL_AddReliableCommand("stopdl", qfalse);
CL_NextDownload();
return;
}
@@ -604,7 +604,7 @@ void CL_ParseDownload ( msg_t *msg ) {
if (size)
FS_Write( data, size, clc.download );
- CL_AddReliableCommand( va("nextdl %d", clc.downloadBlock) );
+ CL_AddReliableCommand(va("nextdl %d", clc.downloadBlock), qfalse);
clc.downloadBlock++;
clc.downloadCount += size;
diff --git a/src/client/client.h b/src/client/client.h
index a6d61950..4d5cd522 100644
--- a/src/client/client.h
+++ b/src/client/client.h
@@ -439,7 +439,7 @@ extern cvar_t *cl_voip;
void CL_Init (void);
void CL_FlushMemory(void);
void CL_ShutdownAll(void);
-void CL_AddReliableCommand( const char *cmd );
+void CL_AddReliableCommand(const char *cmd, qboolean isDisconnectCmd);
void CL_StartHunkUsers( qboolean rendererOnly );
diff --git a/src/client/snd_dma.c b/src/client/snd_dma.c
index c8df2daf..472af0d8 100644
--- a/src/client/snd_dma.c
+++ b/src/client/snd_dma.c
@@ -932,7 +932,7 @@ void S_ByteSwapRawSamples( int samples, int width, int s_channels, const byte *d
/*
============
-S_RawSamples
+S_Base_RawSamples
Music streaming
============
@@ -953,10 +953,10 @@ void S_Base_RawSamples( int stream, int samples, int rate, int width, int s_chan
}
rawsamples = s_rawsamples[stream];
- intVolume = 256 * volume;
+ intVolume = 256 * volume * s_volume->value;
if ( s_rawend[stream] < s_soundtime ) {
- Com_DPrintf( "S_RawSamples: resetting minimum: %i < %i\n", s_rawend[stream], s_soundtime );
+ Com_DPrintf( "S_Base_RawSamples: resetting minimum: %i < %i\n", s_rawend[stream], s_soundtime );
s_rawend[stream] = s_soundtime;
}
@@ -1034,7 +1034,7 @@ void S_Base_RawSamples( int stream, int samples, int rate, int width, int s_chan
}
if ( s_rawend[stream] > s_soundtime + MAX_RAW_SAMPLES ) {
- Com_DPrintf( "S_RawSamples: overflowed %i > %i\n", s_rawend[stream], s_soundtime );
+ Com_DPrintf( "S_Base_RawSamples: overflowed %i > %i\n", s_rawend[stream], s_soundtime );
}
}
diff --git a/src/client/snd_openal.c b/src/client/snd_openal.c
index 1f91ae95..be064697 100644
--- a/src/client/snd_openal.c
+++ b/src/client/snd_openal.c
@@ -99,6 +99,22 @@ static const char *S_AL_ErrorMsg(ALenum error)
}
}
+/*
+=================
+S_AL_ClearError
+=================
+*/
+static void S_AL_ClearError( qboolean quiet )
+{
+ int error = qalGetError();
+
+ if( quiet )
+ return;
+ if(error != AL_NO_ERROR)
+ Com_Printf(S_COLOR_YELLOW "WARNING: unhandled AL error: %s\n",
+ S_AL_ErrorMsg(error));
+}
+
//===========================================================================
@@ -219,7 +235,8 @@ static void S_AL_BufferUnload(sfxHandle_t sfx)
if(!knownSfx[sfx].inMemory)
return;
- // Delete it
+ // Delete it
+ S_AL_ClearError( qfalse );
qalDeleteBuffers(1, &knownSfx[sfx].buffer);
if((error = qalGetError()) != AL_NO_ERROR)
Com_Printf( S_COLOR_RED "ERROR: Can't delete sound buffer for %s\n",
@@ -303,6 +320,7 @@ static void S_AL_BufferLoad(sfxHandle_t sfx)
format = S_AL_Format(info.width, info.channels);
// Create a buffer
+ S_AL_ClearError( qfalse );
qalGenBuffers(1, &knownSfx[sfx].buffer);
if((error = qalGetError()) != AL_NO_ERROR)
{
@@ -636,7 +654,8 @@ qboolean S_AL_SrcInit( void )
limit = MAX_SRC;
else if(limit < 16)
limit = 16;
-
+
+ S_AL_ClearError( qfalse );
// Allocate as many sources as possible
for(i = 0; i < limit; i++)
{
@@ -1559,6 +1578,8 @@ void S_AL_MusicProcess(ALuint b)
ALuint format;
snd_stream_t *curstream;
+ S_AL_ClearError( qfalse );
+
if(intro_stream)
curstream = intro_stream;
else
@@ -1741,7 +1762,7 @@ static cvar_t *s_alCapture;
#elif defined(MACOS_X)
#define ALDRIVER_DEFAULT "/System/Library/Frameworks/OpenAL.framework/OpenAL"
#else
-#define ALDRIVER_DEFAULT "libopenal.so.0"
+#define ALDRIVER_DEFAULT "libopenal.so.1"
#endif
/*
diff --git a/src/qcommon/common.c b/src/qcommon/common.c
index b97626ed..d4593e08 100644
--- a/src/qcommon/common.c
+++ b/src/qcommon/common.c
@@ -672,22 +672,6 @@ int Com_FilterPath(char *filter, char *name, int casesensitive)
}
/*
-============
-Com_HashKey
-============
-*/
-int Com_HashKey(char *string, int maxlen) {
- int register hash, i;
-
- hash = 0;
- for (i = 0; i < maxlen && string[i] != '\0'; i++) {
- hash += string[i] * (119 + i);
- }
- hash = (hash ^ (hash >> 10) ^ (hash >> 20));
- return hash;
-}
-
-/*
================
Com_RealTime
================
@@ -2361,6 +2345,43 @@ static void Com_Crash_f( void ) {
* ( int * ) 0 = 0x12345678;
}
+/*
+==================
+Com_Setenv_f
+
+For controlling environment variables
+==================
+*/
+void Com_Setenv_f(void)
+{
+ int argc = Cmd_Argc();
+ char *arg1 = Cmd_Argv(1);
+
+ if(argc > 2)
+ {
+ char *arg2 = Cmd_ArgsFrom(2);
+
+#ifdef _WIN32
+ // windows already removes env variable if value is an empty string
+ _putenv(va("%s=%s", arg1, arg2));
+#else
+ if(!*arg2)
+ unsetenv(arg1);
+ else
+ setenv(arg1, arg2, 1);
+#endif
+ }
+ else if(argc == 2)
+ {
+ char *env = getenv(arg1);
+
+ if(env)
+ Com_Printf("%s=%s\n", arg1, env);
+ else
+ Com_Printf("%s undefined\n", arg1);
+ }
+}
+
static void Com_DetectAltivec(void)
{
// Only detect if user hasn't forcibly disabled it.
@@ -2445,12 +2466,25 @@ void Com_Init( char *commandLine ) {
Com_InitJournaling();
+ // Add some commands here already so users can use them from config files
+ Cmd_AddCommand ("setenv", Com_Setenv_f);
+ if (com_developer && com_developer->integer)
+ {
+ Cmd_AddCommand ("error", Com_Error_f);
+ Cmd_AddCommand ("crash", Com_Crash_f);
+ Cmd_AddCommand ("freeze", Com_Freeze_f);
+ }
+ Cmd_AddCommand ("quit", Com_Quit_f);
+ Cmd_AddCommand ("changeVectors", MSG_ReportChangeVectors_f );
+ Cmd_AddCommand ("writeconfig", Com_WriteConfig_f );
+ Cmd_SetCommandCompletionFunc( "writeconfig", Cmd_CompleteCfgName );
+
+ // Make it execute the configuration files
Cbuf_AddText ("exec default.cfg\n");
// skip the autogen.cfg if "safe" is on the command line
- if ( !Com_SafeMode() ) {
- Cbuf_AddText ("exec " Q3CONFIG_CFG "\n");
- }
+ if (!Com_SafeMode())
+ Cbuf_AddText("exec " Q3CONFIG_CFG "\n");
Cbuf_AddText ("exec autoexec.cfg\n");
@@ -2506,16 +2540,6 @@ void Com_Init( char *commandLine ) {
com_minimized = Cvar_Get( "com_minimized", "0", CVAR_ROM );
com_maxfpsMinimized = Cvar_Get( "com_maxfpsMinimized", "0", CVAR_ARCHIVE );
- if ( com_developer && com_developer->integer ) {
- Cmd_AddCommand ("error", Com_Error_f);
- Cmd_AddCommand ("crash", Com_Crash_f );
- Cmd_AddCommand ("freeze", Com_Freeze_f);
- }
- Cmd_AddCommand ("quit", Com_Quit_f);
- Cmd_AddCommand ("changeVectors", MSG_ReportChangeVectors_f );
- Cmd_AddCommand ("writeconfig", Com_WriteConfig_f );
- Cmd_SetCommandCompletionFunc( "writeconfig", Cmd_CompleteCfgName );
-
s = va("%s %s %s", Q3_VERSION, PLATFORM_STRING, __DATE__ );
com_version = Cvar_Get ("version", s, CVAR_ROM | CVAR_SERVERINFO );
diff --git a/src/qcommon/files.c b/src/qcommon/files.c
index db7e79d4..75686111 100644
--- a/src/qcommon/files.c
+++ b/src/qcommon/files.c
@@ -250,7 +250,6 @@ static int fs_loadCount; // total files read
static int fs_loadStack; // total files in memory
static int fs_packFiles; // total number of files in packs
-static int fs_fakeChkSum;
static int fs_checksumFeed;
typedef union qfile_gus {
@@ -1175,14 +1174,6 @@ int FS_FOpenFileRead( const char *filename, fileHandle_t *file, qboolean uniqueF
continue;
}
- if ( Q_stricmp( filename + l - 4, ".cfg" ) // for config files
- && Q_stricmp( filename + l - 5, ".menu" ) // menu files
- && Q_stricmp( filename + l - 5, ".game" ) // menu files
- && Q_stricmp( filename + l - strlen(demoExt), demoExt ) // menu files
- && Q_stricmp( filename + l - 4, ".dat" ) ) { // for journal files
- fs_fakeChkSum = random();
- }
-
Q_strncpyz( fsh[*file].name, filename, sizeof( fsh[*file].name ) );
fsh[*file].zipFile = qfalse;
if ( fs_debug->integer ) {
@@ -2994,10 +2985,6 @@ const char *FS_ReferencedPakPureChecksums( void ) {
numPaks++;
}
}
- if (fs_fakeChkSum != 0) {
- // only added if a non-pure file is referenced
- Q_strcat( info, sizeof( info ), va("%i ", fs_fakeChkSum ) );
- }
}
// last checksum is the encoded number of referenced pk3s
checksum ^= numPaks;
diff --git a/src/qcommon/msg.c b/src/qcommon/msg.c
index 3d3355ec..9893a65a 100644
--- a/src/qcommon/msg.c
+++ b/src/qcommon/msg.c
@@ -312,9 +312,9 @@ void MSG_WriteString( msg_t *sb, const char *s ) {
}
Q_strncpyz( string, s, sizeof( string ) );
- // get rid of 0xff chars, because old clients don't like them
+ // get rid of 0x80+ and '%' chars, because old clients don't like them
for ( i = 0 ; i < l ; i++ ) {
- if ( ((byte *)string)[i] > 127 ) {
+ if ( ((byte *)string)[i] > 127 || string[i] == '%' ) {
string[i] = '.';
}
}
@@ -338,9 +338,9 @@ void MSG_WriteBigString( msg_t *sb, const char *s ) {
}
Q_strncpyz( string, s, sizeof( string ) );
- // get rid of 0xff chars, because old clients don't like them
+ // get rid of 0x80+ and '%' chars, because old clients don't like them
for ( i = 0 ; i < l ; i++ ) {
- if ( ((byte *)string)[i] > 127 ) {
+ if ( ((byte *)string)[i] > 127 || string[i] == '%' ) {
string[i] = '.';
}
}
@@ -514,6 +514,21 @@ void MSG_ReadData( msg_t *msg, void *data, int len ) {
}
}
+// a string hasher which gives the same hash value even if the
+// string is later modified via the legacy MSG read/write code
+int MSG_HashKey(const char *string, int maxlen) {
+ int hash, i;
+
+ hash = 0;
+ for (i = 0; i < maxlen && string[i] != '\0'; i++) {
+ if (string[i] & 0x80 || string[i] == '%')
+ hash += '.' * (119 + i);
+ else
+ hash += string[i] * (119 + i);
+ }
+ hash = (hash ^ (hash >> 10) ^ (hash >> 20));
+ return hash;
+}
/*
=============================================================================
diff --git a/src/qcommon/q_shared.h b/src/qcommon/q_shared.h
index 59c5b91d..0cf4ca91 100644
--- a/src/qcommon/q_shared.h
+++ b/src/qcommon/q_shared.h
@@ -368,20 +368,20 @@ extern vec4_t colorMdGrey;
extern vec4_t colorDkGrey;
#define Q_COLOR_ESCAPE '^'
-#define Q_IsColorString(p) ( p && *(p) == Q_COLOR_ESCAPE && *((p)+1) && isalnum(*((p)+1)) ) // ^[0-9a-zA-Z]
+#define Q_IsColorString(p) ((p) && *(p) == Q_COLOR_ESCAPE && *((p)+1) && isalnum(*((p)+1))) // ^[0-9a-zA-Z]
-#define COLOR_BLACK '0'
-#define COLOR_RED '1'
-#define COLOR_GREEN '2'
+#define COLOR_BLACK '0'
+#define COLOR_RED '1'
+#define COLOR_GREEN '2'
#define COLOR_YELLOW '3'
-#define COLOR_BLUE '4'
-#define COLOR_CYAN '5'
+#define COLOR_BLUE '4'
+#define COLOR_CYAN '5'
#define COLOR_MAGENTA '6'
-#define COLOR_WHITE '7'
-#define ColorIndex(c) ( ( (c) - '0' ) & 7 )
+#define COLOR_WHITE '7'
+#define ColorIndex(c) (((c) - '0') & 0x07)
#define S_COLOR_BLACK "^0"
-#define S_COLOR_RED "^1"
+#define S_COLOR_RED "^1"
#define S_COLOR_GREEN "^2"
#define S_COLOR_YELLOW "^3"
#define S_COLOR_BLUE "^4"
diff --git a/src/qcommon/qcommon.h b/src/qcommon/qcommon.h
index bcfd60b9..d240c2d1 100644
--- a/src/qcommon/qcommon.h
+++ b/src/qcommon/qcommon.h
@@ -75,6 +75,7 @@ void MSG_WriteFloat (msg_t *sb, float f);
void MSG_WriteString (msg_t *sb, const char *s);
void MSG_WriteBigString (msg_t *sb, const char *s);
void MSG_WriteAngle16 (msg_t *sb, float f);
+int MSG_HashKey(const char *string, int maxlen);
void MSG_BeginReading (msg_t *sb);
void MSG_BeginReadingOOB(msg_t *sb);
@@ -786,7 +787,6 @@ void Com_Quit_f( void );
int Com_Milliseconds( void ); // will be journaled properly
unsigned Com_BlockChecksum( const void *buffer, int length );
char *Com_MD5File(const char *filename, int length, const char *prefix, int prefix_len);
-int Com_HashKey(char *string, int maxlen);
int Com_Filter(char *filter, char *name, int casesensitive);
int Com_FilterPath(char *filter, char *name, int casesensitive);
int Com_RealTime(qtime_t *qtime);
diff --git a/src/qcommon/vm_x86_64_assembler.c b/src/qcommon/vm_x86_64_assembler.c
index be295e3a..5747626a 100644
--- a/src/qcommon/vm_x86_64_assembler.c
+++ b/src/qcommon/vm_x86_64_assembler.c
@@ -593,7 +593,7 @@ static void emit_mov(const char* mnemonic, arg_t arg1, arg_t arg2, void* data)
crap("value too large for 16bit register");
emit1(0x66);
}
- else if(!arg2.v.reg & R_64)
+ else if(!(arg2.v.reg & R_64))
{
if(!isu32(arg1.v.imm))
crap("value too large for 32bit register");
diff --git a/src/server/server.h b/src/server/server.h
index fca29aae..a41dba91 100644
--- a/src/server/server.h
+++ b/src/server/server.h
@@ -216,6 +216,7 @@ typedef struct {
int time; // time the last packet was sent to the autherize server
int pingTime; // time the challenge response was sent to client
int firstTime; // time the adr was first used, for authorize timeout checks
+ qboolean wasrefused;
qboolean connected;
} challenge_t;
diff --git a/src/server/sv_client.c b/src/server/sv_client.c
index 319f865e..92c4d5f1 100644
--- a/src/server/sv_client.c
+++ b/src/server/sv_client.c
@@ -65,7 +65,7 @@ void SV_GetChallenge(netadr_t from)
// see if we already have a challenge for this ip
challenge = &svs.challenges[0];
for (i = 0 ; i < MAX_CHALLENGES ; i++, challenge++) {
- if ( !challenge->connected && NET_CompareAdr( from, challenge->adr ) ) {
+ if (!challenge->connected && NET_CompareAdr( from, challenge->adr ) ) {
break;
}
if ( challenge->time < oldestTime ) {
@@ -78,7 +78,6 @@ void SV_GetChallenge(netadr_t from)
{
// this is the first time this client has asked for a challenge
challenge = &svs.challenges[oldest];
- challenge->challenge = ( (rand() << 16) ^ rand() ) ^ svs.time;
challenge->clientChallenge = 0;
challenge->adr = from;
challenge->firstTime = svs.time;
@@ -86,9 +85,9 @@ void SV_GetChallenge(netadr_t from)
challenge->connected = qfalse;
}
- // send the challengeResponse
- challenge->pingTime = svs.time;
- NET_OutOfBandPrint( NS_SERVER, from, "challengeResponse %i", challenge->challenge );
+ // always generate a new challenge number, so the client cannot circumvent sv_maxping
+ challenge->challenge = ( (rand() << 16) ^ rand() ) ^ svs.time;
+ challenge->wasrefused = qfalse;
challenge->pingTime = svs.time;
NET_OutOfBandPrint( NS_SERVER, challenge->adr, "challengeResponse %i %s", challenge->challenge, clientChallenge);
@@ -162,41 +161,53 @@ void SV_DirectConnect( netadr_t from ) {
Info_SetValueForKey( userinfo, "ip", ip );
// see if the challenge is valid (LAN clients don't need to challenge)
- if ( !NET_IsLocalAddress (from) ) {
- int ping;
+ if (!NET_IsLocalAddress(from))
+ {
+ int ping;
+ challenge_t *challengeptr;
- for (i=0 ; i<MAX_CHALLENGES ; i++) {
- if (NET_CompareAdr(from, svs.challenges[i].adr)) {
- if ( challenge == svs.challenges[i].challenge )
+ for (i=0; i<MAX_CHALLENGES; i++)
+ {
+ if (NET_CompareAdr(from, svs.challenges[i].adr))
+ {
+ if(challenge == svs.challenges[i].challenge)
break;
}
}
- if (i == MAX_CHALLENGES) {
- NET_OutOfBandPrint( NS_SERVER, from, "print\nNo or bad challenge for address\n" );
+ if (i == MAX_CHALLENGES)
+ {
+ NET_OutOfBandPrint( NS_SERVER, from, "print\nNo or bad challenge for your address.\n" );
+ return;
+ }
+
+ challengeptr = &svs.challenges[i];
+
+ if(challengeptr->wasrefused)
+ {
+ // Return silently, so that error messages written by the server keep being displayed.
return;
}
- ping = svs.time - svs.challenges[i].pingTime;
- Com_Printf( "Client %i connecting with %i challenge ping\n", i, ping );
- svs.challenges[i].connected = qtrue;
+ ping = svs.time - challengeptr->pingTime;
// never reject a LAN client based on ping
if ( !Sys_IsLANAddress( from ) ) {
if ( sv_minPing->value && ping < sv_minPing->value ) {
- // don't let them keep trying until they get a big delay
NET_OutOfBandPrint( NS_SERVER, from, "print\nServer is for high pings only\n" );
Com_DPrintf ("Client %i rejected on a too low ping\n", i);
- // reset the address otherwise their ping will keep increasing
- // with each connect message and they'd eventually be able to connect
- svs.challenges[i].adr.port = 0;
+ challengeptr->wasrefused = qtrue;
return;
}
if ( sv_maxPing->value && ping > sv_maxPing->value ) {
NET_OutOfBandPrint( NS_SERVER, from, "print\nServer is for low pings only\n" );
Com_DPrintf ("Client %i rejected on a too high ping\n", i);
+ challengeptr->wasrefused = qtrue;
return;
}
}
+
+ Com_Printf("Client %i connecting with %i challenge ping\n", i, ping);
+ challengeptr->connected = qtrue;
}
newcl = &temp;
@@ -1197,7 +1208,7 @@ void SV_UpdateVoipIgnore(client_t *cl, const char *idstr, qboolean ignore)
/*
==================
-SV_UpdateUserinfo_f
+SV_Voip_f
==================
*/
static void SV_Voip_f( client_t *cl ) {
@@ -1390,7 +1401,7 @@ static void SV_UserMove( client_t *cl, msg_t *msg, qboolean delta ) {
// also use the message acknowledge
key ^= cl->messageAcknowledge;
// also use the last acknowledged server command in the key
- key ^= Com_HashKey(cl->reliableCommands[ cl->reliableAcknowledge & (MAX_RELIABLE_COMMANDS-1) ], 32);
+ key ^= MSG_HashKey(cl->reliableCommands[ cl->reliableAcknowledge & (MAX_RELIABLE_COMMANDS-1) ], 32);
Com_Memset( &nullcmd, 0, sizeof(nullcmd) );
oldcmd = &nullcmd;