diff options
author | Tim Angus <tim@ngus.net> | 2009-10-09 22:24:05 +0000 |
---|---|---|
committer | Tim Angus <tim@ngus.net> | 2013-01-03 00:16:45 +0000 |
commit | a1f3d889f1eca9b3a670363dd386480ec2b48a76 (patch) | |
tree | 80452d051386e4ca98efed6d2cd6f762416b46e7 | |
parent | d28ad7411a91881d168d45d0846adf80a579a02f (diff) |
* (bug #3836) Add [SV|trap]_SetConfigstringRestrictions which prevents some
clients receiving a config string
* Move BG_ClientList* to Com_ClientList*
* Split CS_STAGES into CS_ALIEN_STAGES and CS_HUMAN_STAGES
-rw-r--r-- | src/cgame/cg_main.c | 10 | ||||
-rw-r--r-- | src/cgame/cg_players.c | 2 | ||||
-rw-r--r-- | src/cgame/cg_servercmds.c | 65 | ||||
-rw-r--r-- | src/game/bg_misc.c | 79 | ||||
-rw-r--r-- | src/game/bg_public.h | 14 | ||||
-rw-r--r-- | src/game/g_client.c | 4 | ||||
-rw-r--r-- | src/game/g_cmds.c | 12 | ||||
-rw-r--r-- | src/game/g_local.h | 1 | ||||
-rw-r--r-- | src/game/g_main.c | 26 | ||||
-rw-r--r-- | src/game/g_public.h | 2 | ||||
-rw-r--r-- | src/game/g_session.c | 4 | ||||
-rw-r--r-- | src/game/g_syscalls.asm | 119 | ||||
-rw-r--r-- | src/game/g_syscalls.c | 5 | ||||
-rw-r--r-- | src/game/g_team.c | 58 | ||||
-rw-r--r-- | src/qcommon/q_shared.c | 79 | ||||
-rw-r--r-- | src/qcommon/q_shared.h | 12 | ||||
-rw-r--r-- | src/server/server.h | 10 | ||||
-rw-r--r-- | src/server/sv_client.c | 4 | ||||
-rw-r--r-- | src/server/sv_game.c | 3 | ||||
-rw-r--r-- | src/server/sv_init.c | 54 | ||||
-rw-r--r-- | src/ui/ui_main.c | 20 |
21 files changed, 369 insertions, 214 deletions
diff --git a/src/cgame/cg_main.c b/src/cgame/cg_main.c index 01c24579..e0a9e83c 100644 --- a/src/cgame/cg_main.c +++ b/src/cgame/cg_main.c @@ -1430,9 +1430,9 @@ static qboolean CG_ClientIsReady( int clientNum ) { clientList_t ready; - BG_ClientListParse( &ready, CG_ConfigString( CS_CLIENTS_READY ) ); + Com_ClientListParse( &ready, CG_ConfigString( CS_CLIENTS_READY ) ); - return BG_ClientListTest( &ready, clientNum ); + return Com_ClientListContains( &ready, clientNum ); } static const char *CG_FeederItemText( float feederID, int index, int column, qhandle_t *handle ) @@ -1761,13 +1761,13 @@ void CG_Init( int serverMessageNum, int serverCommandSequence, int clientNum ) // get the gamestate from the client system trap_GetGameState( &cgs.gameState ); - // copy vote display strings so they don't show up blank if we see + // copy vote display strings so they don't show up blank if we see // the same one directly after connecting Q_strncpyz( cgs.voteString[ TEAM_NONE ], - CG_ConfigString( CS_VOTE_STRING + TEAM_NONE ), + CG_ConfigString( CS_VOTE_STRING + TEAM_NONE ), sizeof( cgs.voteString ) ); Q_strncpyz( cgs.voteString[ TEAM_ALIENS ], - CG_ConfigString( CS_VOTE_STRING + TEAM_ALIENS ), + CG_ConfigString( CS_VOTE_STRING + TEAM_ALIENS ), sizeof( cgs.voteString[ TEAM_ALIENS ] ) ); Q_strncpyz( cgs.voteString[ TEAM_HUMANS ], CG_ConfigString( CS_VOTE_STRING + TEAM_ALIENS ), diff --git a/src/cgame/cg_players.c b/src/cgame/cg_players.c index 2cef1539..5e9d292c 100644 --- a/src/cgame/cg_players.c +++ b/src/cgame/cg_players.c @@ -796,7 +796,7 @@ void CG_NewClientInfo( int clientNum ) if( clientNum == cg.predictedPlayerState.clientNum ) { v = Info_ValueForKey( configstring, "ig" ); - BG_ClientListParse( &cgs.ignoreList, v ); + Com_ClientListParse( &cgs.ignoreList, v ); } // isolate the player's name diff --git a/src/cgame/cg_servercmds.c b/src/cgame/cg_servercmds.c index 8e18fd9c..78769644 100644 --- a/src/cgame/cg_servercmds.c +++ b/src/cgame/cg_servercmds.c @@ -160,8 +160,25 @@ Called on load to set the initial values from configure strings */ void CG_SetConfigValues( void ) { - sscanf( CG_ConfigString( CS_STAGES ), "%d %d %d %d %d %d", &cgs.alienStage, &cgs.humanStage, - &cgs.alienCredits, &cgs.humanCredits, &cgs.alienNextStageThreshold, &cgs.humanNextStageThreshold ); + const char *alienStages = CG_ConfigString( CS_ALIEN_STAGES ); + const char *humanStages = CG_ConfigString( CS_HUMAN_STAGES ); + + if( alienStages[0] ) + { + sscanf( alienStages, "%d %d %d", &cgs.alienStage, &cgs.alienCredits, + &cgs.alienNextStageThreshold ); + } + else + cgs.alienStage = cgs.alienCredits = cgs.alienNextStageThreshold = 0; + + + if( humanStages[0] ) + { + sscanf( humanStages, "%d %d %d", &cgs.humanStage, &cgs.humanCredits, + &cgs.humanNextStageThreshold ); + } + else + cgs.humanStage = cgs.humanCredits = cgs.humanNextStageThreshold = 0; cgs.levelStartTime = atoi( CG_ConfigString( CS_LEVEL_START_TIME ) ); cg.warmup = atoi( CG_ConfigString( CS_WARMUP ) ); @@ -273,21 +290,39 @@ static void CG_ConfigStringModified( void ) CG_ParseServerinfo( ); else if( num == CS_WARMUP ) CG_ParseWarmup( ); - else if( num == CS_STAGES ) + else if( num == CS_ALIEN_STAGES ) { stage_t oldAlienStage = cgs.alienStage; - stage_t oldHumanStage = cgs.humanStage; - sscanf( str, "%d %d %d %d %d %d", - &cgs.alienStage, &cgs.humanStage, - &cgs.alienCredits, &cgs.humanCredits, - &cgs.alienNextStageThreshold, &cgs.humanNextStageThreshold ); + if( str[0] ) + { + sscanf( str, "%d %d %d", &cgs.alienStage, &cgs.alienCredits, + &cgs.alienNextStageThreshold ); + + if( cgs.alienStage != oldAlienStage ) + CG_AnnounceAlienStageTransistion( oldAlienStage, cgs.alienStage ); + } + else + { + cgs.alienStage = cgs.alienCredits = cgs.alienNextStageThreshold = 0; + } + } + else if( num == CS_HUMAN_STAGES ) + { + stage_t oldHumanStage = cgs.humanStage; - if( cgs.alienStage != oldAlienStage ) - CG_AnnounceAlienStageTransistion( oldAlienStage, cgs.alienStage ); + if( str[0] ) + { + sscanf( str, "%d %d %d", &cgs.humanStage, &cgs.humanCredits, + &cgs.humanNextStageThreshold ); - if( cgs.humanStage != oldHumanStage ) - CG_AnnounceHumanStageTransistion( oldHumanStage, cgs.humanStage ); + if( cgs.humanStage != oldHumanStage ) + CG_AnnounceHumanStageTransistion( oldHumanStage, cgs.humanStage ); + } + else + { + cgs.humanStage = cgs.humanCredits = cgs.humanNextStageThreshold = 0; + } } else if( num == CS_LEVEL_START_TIME ) cgs.levelStartTime = atoi( str ); @@ -895,7 +930,7 @@ static void CG_Say( int clientNum, char *text ) "%s: " S_COLOR_WHITE S_COLOR_GREEN "%s" S_COLOR_WHITE "\n", ci->name, text ); - if( BG_ClientListTest( &cgs.ignoreList, clientNum ) ) + if( Com_ClientListContains( &cgs.ignoreList, clientNum ) ) CG_Printf( "[skipnotify]%s", sayText ); else CG_Printf( "%s", sayText ); @@ -919,7 +954,7 @@ static void CG_SayTeam( int clientNum, char *text ) "%s: " S_COLOR_CYAN "%s" S_COLOR_WHITE "\n", ci->name, text ); - if( BG_ClientListTest( &cgs.ignoreList, clientNum ) ) + if( Com_ClientListContains( &cgs.ignoreList, clientNum ) ) CG_Printf( "[skipnotify]%s", sayText ); else CG_Printf( "%s", sayText ); @@ -1042,7 +1077,7 @@ static void CG_ParseVoice( void ) return; // don't play audio track for lamers - if( BG_ClientListTest( &cgs.ignoreList, clientNum ) ) + if( Com_ClientListContains( &cgs.ignoreList, clientNum ) ) return; switch( vChan ) diff --git a/src/game/bg_misc.c b/src/game/bg_misc.c index 1be45648..f9cdb545 100644 --- a/src/game/bg_misc.c +++ b/src/game/bg_misc.c @@ -3849,85 +3849,6 @@ qboolean BG_BuildableIsAllowed( buildable_t buildable ) /* ============ -BG_ClientListTest -============ -*/ -qboolean BG_ClientListTest( clientList_t *list, int clientNum ) -{ - if( clientNum < 0 || clientNum >= MAX_CLIENTS || !list ) - return qfalse; - if( clientNum < 32 ) - return ( ( list->lo & ( 1 << clientNum ) ) != 0 ); - else - return ( ( list->hi & ( 1 << ( clientNum - 32 ) ) ) != 0 ); -} - -/* -============ -BG_ClientListAdd -============ -*/ -void BG_ClientListAdd( clientList_t *list, int clientNum ) -{ - if( clientNum < 0 || clientNum >= MAX_CLIENTS || !list ) - return; - if( clientNum < 32 ) - list->lo |= ( 1 << clientNum ); - else - list->hi |= ( 1 << ( clientNum - 32 ) ); -} - -/* -============ -BG_ClientListRemove -============ -*/ -void BG_ClientListRemove( clientList_t *list, int clientNum ) -{ - if( clientNum < 0 || clientNum >= MAX_CLIENTS || !list ) - return; - if( clientNum < 32 ) - list->lo &= ~( 1 << clientNum ); - else - list->hi &= ~( 1 << ( clientNum - 32 ) ); -} - -/* -============ -BG_ClientListString -============ -*/ -char *BG_ClientListString( clientList_t *list ) -{ - static char s[ 17 ]; - - s[ 0 ] = '\0'; - if( !list ) - return s; - Com_sprintf( s, sizeof( s ), "%08x%08x", list->hi, list->lo ); - return s; -} - -/* -============ -BG_ClientListParse -============ -*/ -void BG_ClientListParse( clientList_t *list, const char *s ) -{ - if( !list ) - return; - list->lo = 0; - list->hi = 0; - if( !s ) - return; - if( strlen( s ) != 16 ) - return; - sscanf( s, "%x%x", &list->hi, &list->lo ); -} - -/* -============ BG_PrimaryWeapon ============ */ diff --git a/src/game/bg_public.h b/src/game/bg_public.h index 480139cf..9649de98 100644 --- a/src/game/bg_public.h +++ b/src/game/bg_public.h @@ -64,7 +64,8 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #define CS_BOTINFO 25 #define CS_CLIENTS_READY 26 -#define CS_STAGES 29 +#define CS_ALIEN_STAGES 29 +#define CS_HUMAN_STAGES 30 #define CS_MODELS 33 #define CS_SOUNDS (CS_MODELS+MAX_MODELS) @@ -1232,17 +1233,6 @@ qboolean BG_ClassIsAllowed( class_t class ); qboolean BG_BuildableIsAllowed( buildable_t buildable ); weapon_t BG_PrimaryWeapon( int stats[ ] ); -typedef struct -{ - unsigned int hi; - unsigned int lo; -} clientList_t; -qboolean BG_ClientListTest( clientList_t *list, int clientNum ); -void BG_ClientListAdd( clientList_t *list, int clientNum ); -void BG_ClientListRemove( clientList_t *list, int clientNum ); -char *BG_ClientListString( clientList_t *list ); -void BG_ClientListParse( clientList_t *list, const char *s ); - // Friendly Fire Flags #define FFF_HUMANS 1 #define FFF_ALIENS 2 diff --git a/src/game/g_client.c b/src/game/g_client.c index 8fe6ae96..34740958 100644 --- a/src/game/g_client.c +++ b/src/game/g_client.c @@ -1173,7 +1173,7 @@ void ClientUserinfoChanged( int clientNum ) "n\\%s\\t\\%i\\model\\%s\\c1\\%s\\c2\\%s\\" "hc\\%i\\ig\\%16s\\v\\%s", client->pers.netname, client->pers.teamSelection, model, c1, c2, - client->pers.maxHealth, BG_ClientListString( &client->sess.ignoreList ), + client->pers.maxHealth, Com_ClientListString( &client->sess.ignoreList ), client->pers.voice ); trap_SetConfigstring( CS_PLAYERS + clientNum, userinfo ); @@ -1694,7 +1694,7 @@ void ClientDisconnect( int clientNum ) for( i = 0; i < level.maxclients; i++ ) { // remove any /ignore settings for this clientNum - BG_ClientListRemove( &level.clients[ i ].sess.ignoreList, clientNum ); + Com_ClientListRemove( &level.clients[ i ].sess.ignoreList, clientNum ); } // send effect if they were completely connected diff --git a/src/game/g_cmds.c b/src/game/g_cmds.c index 9cda473e..ce3a5b36 100644 --- a/src/game/g_cmds.c +++ b/src/game/g_cmds.c @@ -691,7 +691,7 @@ static void G_SayTo( gentity_t *ent, gentity_t *other, int mode, int color, cons // specs with ADMF_SPEC_ALLCHAT flag can see team chat } - if( ent && BG_ClientListTest( &other->client->sess.ignoreList, ent-g_entities ) ) + if( ent && Com_ClientListContains( &other->client->sess.ignoreList, ent-g_entities ) ) ignore = qtrue; trap_SendServerCommand( other-g_entities, va( "%s \"%s%s%c%c%s%s\"", @@ -2751,9 +2751,9 @@ static void Cmd_Ignore_f( gentity_t *ent ) { if( ignore ) { - if( !BG_ClientListTest( &ent->client->sess.ignoreList, pids[ i ] ) ) + if( !Com_ClientListContains( &ent->client->sess.ignoreList, pids[ i ] ) ) { - BG_ClientListAdd( &ent->client->sess.ignoreList, pids[ i ] ); + Com_ClientListAdd( &ent->client->sess.ignoreList, pids[ i ] ); ClientUserinfoChanged( ent->client->ps.clientNum ); trap_SendServerCommand( ent-g_entities, va( "print \"[skipnotify]" "ignore: added %s^7 to your ignore list\n\"", @@ -2768,9 +2768,9 @@ static void Cmd_Ignore_f( gentity_t *ent ) } else { - if( BG_ClientListTest( &ent->client->sess.ignoreList, pids[ i ] ) ) + if( Com_ClientListContains( &ent->client->sess.ignoreList, pids[ i ] ) ) { - BG_ClientListRemove( &ent->client->sess.ignoreList, pids[ i ] ); + Com_ClientListRemove( &ent->client->sess.ignoreList, pids[ i ] ); ClientUserinfoChanged( ent->client->ps.clientNum ); trap_SendServerCommand( ent-g_entities, va( "print \"[skipnotify]" "unignore: removed %s^7 from your ignore list\n\"", @@ -3155,7 +3155,7 @@ void Cmd_PrivateMessage_f( gentity_t *ent ) if( teamonly && !OnSameTeam( ent, tmpent ) ) continue; - if( BG_ClientListTest( &tmpent->client->sess.ignoreList, + if( Com_ClientListContains( &tmpent->client->sess.ignoreList, ent-g_entities ) ) { ignoreids[ ignored++ ] = pids[ i ]; diff --git a/src/game/g_local.h b/src/game/g_local.h index afafe587..1ec22e51 100644 --- a/src/game/g_local.h +++ b/src/game/g_local.h @@ -1161,6 +1161,7 @@ void trap_DropClient( int clientNum, const char *reason ); void trap_SendServerCommand( int clientNum, const char *text ); void trap_SetConfigstring( int num, const char *string ); void trap_GetConfigstring( int num, char *buffer, int bufferSize ); +void trap_SetConfigstringRestrictions( int num, const clientList_t *clientList ); void trap_GetUserinfo( int num, char *buffer, int bufferSize ); void trap_SetUserinfo( int num, const char *buffer ); void trap_GetServerinfo( char *buffer, int bufferSize ); diff --git a/src/game/g_main.c b/src/game/g_main.c index 0343353e..33343b23 100644 --- a/src/game/g_main.c +++ b/src/game/g_main.c @@ -635,7 +635,7 @@ void G_InitGame( int levelTime, int randomSeed, int restart ) level.suddenDeathBeginTime = g_suddenDeathTime.integer * 60000; G_Printf( "-----------------------------------\n" ); - + // So the server counts the spawns without a client attached G_CountSpawns( ); @@ -1312,10 +1312,13 @@ void G_CalculateStages( void ) if( humanNextStageThreshold > 0 ) humanNextStageThreshold = ceil( (float)humanNextStageThreshold / 100 ) * 100; - trap_SetConfigstring( CS_STAGES, va( "%d %d %d %d %d %d", - g_alienStage.integer, g_humanStage.integer, - g_alienCredits.integer, g_humanCredits.integer, - alienNextStageThreshold, humanNextStageThreshold ) ); + trap_SetConfigstring( CS_ALIEN_STAGES, va( "%d %d %d", + g_alienStage.integer, g_alienCredits.integer, + alienNextStageThreshold ) ); + + trap_SetConfigstring( CS_HUMAN_STAGES, va( "%d %d %d", + g_humanStage.integer, g_humanCredits.integer, + humanNextStageThreshold ) ); } /* @@ -1874,13 +1877,13 @@ void CheckIntermissionExit( void ) { ready++; - BG_ClientListAdd( &readyMasks, i ); + Com_ClientListAdd( &readyMasks, i ); } else notReady++; } - trap_SetConfigstring( CS_CLIENTS_READY, BG_ClientListString( &readyMasks ) ); + trap_SetConfigstring( CS_CLIENTS_READY, Com_ClientListString( &readyMasks ) ); // never exit in less than five seconds if( level.time < level.intermissiontime + 5000 ) @@ -2030,8 +2033,10 @@ void G_Vote( gentity_t *ent, team_t team, qboolean voting ) if( voting && ent->client->pers.voted[ team ] ) return; + if( !voting && !ent->client->pers.voted[ team ] ) return; + ent->client->pers.voted[ team ] = voting; if( ent->client->pers.vote[ team ] ) @@ -2040,6 +2045,7 @@ void G_Vote( gentity_t *ent, team_t team, qboolean voting ) level.voteYes[ team ]++; else level.voteYes[ team ]--; + trap_SetConfigstring( CS_VOTE_YES + team, va( "%d", level.voteYes[ team ] ) ); } @@ -2049,6 +2055,7 @@ void G_Vote( gentity_t *ent, team_t team, qboolean voting ) level.voteNo[ team ]++; else level.voteNo[ team ]--; + trap_SetConfigstring( CS_VOTE_NO + team, va( "%d", level.voteNo[ team ] ) ); } @@ -2092,8 +2099,8 @@ void CheckVote( team_t team ) if( !level.voteTime[ team ] ) return; - - if( ( level.time - level.voteTime[ team ] >= VOTE_TIME ) || + + if( ( level.time - level.voteTime[ team ] >= VOTE_TIME ) || ( level.voteYes[ team ] + level.voteNo[ team ] == level.numVotingClients[ team ] ) ) { pass = (float)level.voteYes[ team ] / 100.0f > votePassThreshold || @@ -2119,6 +2126,7 @@ void CheckVote( team_t team ) msg = va( "print \"%sote %sed (%d - %d)\n\"", team == TEAM_NONE ? "V" : "Team v", pass ? "pass" : "fail", level.voteYes[ team ], level.voteNo[ team ] ); + if( team == TEAM_NONE ) trap_SendServerCommand( -1, msg ); else diff --git a/src/game/g_public.h b/src/game/g_public.h index 8c9b4ad8..abccafda 100644 --- a/src/game/g_public.h +++ b/src/game/g_public.h @@ -155,6 +155,8 @@ typedef enum { G_GET_CONFIGSTRING, // ( int num, char *buffer, int bufferSize ); + G_SET_CONFIGSTRING_RESTRICTIONS, // ( int num, const clientList* clientList ); + G_GET_USERINFO, // ( int num, char *buffer, int bufferSize ); // userinfo strings are maintained by the server system, so they // are persistant across level loads, while all other game visible diff --git a/src/game/g_session.c b/src/game/g_session.c index f6b46285..cce6c792 100644 --- a/src/game/g_session.c +++ b/src/game/g_session.c @@ -50,7 +50,7 @@ void G_WriteClientSessionData( gclient_t *client ) client->sess.spectatorTime, client->sess.spectatorState, client->sess.spectatorClient, - BG_ClientListString( &client->sess.ignoreList ) + Com_ClientListString( &client->sess.ignoreList ) ); var = va( "session%i", client - level.clients ); @@ -83,7 +83,7 @@ void G_ReadSessionData( gclient_t *client ) ); client->sess.spectatorState = (spectatorState_t)spectatorState; - BG_ClientListParse( &client->sess.ignoreList, ignorelist ); + Com_ClientListParse( &client->sess.ignoreList, ignorelist ); } diff --git a/src/game/g_syscalls.asm b/src/game/g_syscalls.asm index 132ca1e1..c2b43dbf 100644 --- a/src/game/g_syscalls.asm +++ b/src/game/g_syscalls.asm @@ -1,65 +1,66 @@ code -equ trap_Print -1 -equ trap_Error -2 -equ trap_Milliseconds -3 -equ trap_Cvar_Register -4 -equ trap_Cvar_Update -5 -equ trap_Cvar_Set -6 -equ trap_Cvar_VariableIntegerValue -7 -equ trap_Cvar_VariableStringBuffer -8 -equ trap_Argc -9 -equ trap_Argv -10 -equ trap_FS_FOpenFile -11 -equ trap_FS_Read -12 -equ trap_FS_Write -13 -equ trap_FS_FCloseFile -14 -equ trap_SendConsoleCommand -15 -equ trap_LocateGameData -16 -equ trap_DropClient -17 -equ trap_SendServerCommand -18 -equ trap_SetConfigstring -19 -equ trap_GetConfigstring -20 -equ trap_GetUserinfo -21 -equ trap_SetUserinfo -22 -equ trap_GetServerinfo -23 -equ trap_SetBrushModel -24 -equ trap_Trace -25 -equ trap_PointContents -26 -equ trap_InPVS -27 -equ trap_InPVSIgnorePortals -28 -equ trap_AdjustAreaPortalState -29 -equ trap_AreasConnected -30 -equ trap_LinkEntity -31 -equ trap_UnlinkEntity -32 -equ trap_EntitiesInBox -33 -equ trap_EntityContact -34 -equ trap_GetUsercmd -35 -equ trap_GetEntityToken -36 -equ trap_FS_GetFileList -37 -equ trap_RealTime -38 -equ trap_SnapVector -39 -equ trap_TraceCapsule -40 -equ trap_EntityContactCapsule -41 -equ trap_FS_Seek -42 +equ trap_Print -1 +equ trap_Error -2 +equ trap_Milliseconds -3 +equ trap_Cvar_Register -4 +equ trap_Cvar_Update -5 +equ trap_Cvar_Set -6 +equ trap_Cvar_VariableIntegerValue -7 +equ trap_Cvar_VariableStringBuffer -8 +equ trap_Argc -9 +equ trap_Argv -10 +equ trap_FS_FOpenFile -11 +equ trap_FS_Read -12 +equ trap_FS_Write -13 +equ trap_FS_FCloseFile -14 +equ trap_SendConsoleCommand -15 +equ trap_LocateGameData -16 +equ trap_DropClient -17 +equ trap_SendServerCommand -18 +equ trap_SetConfigstring -19 +equ trap_GetConfigstring -20 +equ trap_SetConfigstringRestrictions -21 +equ trap_GetUserinfo -22 +equ trap_SetUserinfo -23 +equ trap_GetServerinfo -24 +equ trap_SetBrushModel -25 +equ trap_Trace -26 +equ trap_PointContents -27 +equ trap_InPVS -28 +equ trap_InPVSIgnorePortals -29 +equ trap_AdjustAreaPortalState -30 +equ trap_AreasConnected -31 +equ trap_LinkEntity -32 +equ trap_UnlinkEntity -33 +equ trap_EntitiesInBox -34 +equ trap_EntityContact -35 +equ trap_GetUsercmd -36 +equ trap_GetEntityToken -37 +equ trap_FS_GetFileList -38 +equ trap_RealTime -39 +equ trap_SnapVector -40 +equ trap_TraceCapsule -41 +equ trap_EntityContactCapsule -42 +equ trap_FS_Seek -43 -equ trap_Parse_AddGlobalDefine -43 -equ trap_Parse_LoadSource -44 -equ trap_Parse_FreeSource -45 -equ trap_Parse_ReadToken -46 -equ trap_Parse_SourceFileAndLine -47 +equ trap_Parse_AddGlobalDefine -44 +equ trap_Parse_LoadSource -45 +equ trap_Parse_FreeSource -46 +equ trap_Parse_ReadToken -47 +equ trap_Parse_SourceFileAndLine -48 -equ trap_SendGameStat -48 +equ trap_SendGameStat -49 -equ memset -101 -equ memcpy -102 -equ strncpy -103 -equ sin -104 -equ cos -105 -equ atan2 -106 -equ sqrt -107 -equ floor -111 -equ ceil -112 -equ testPrintInt -113 -equ testPrintFloat -114 +equ memset -101 +equ memcpy -102 +equ strncpy -103 +equ sin -104 +equ cos -105 +equ atan2 -106 +equ sqrt -107 +equ floor -111 +equ ceil -112 +equ testPrintInt -113 +equ testPrintFloat -114 diff --git a/src/game/g_syscalls.c b/src/game/g_syscalls.c index 7b030c8a..3a1cd26f 100644 --- a/src/game/g_syscalls.c +++ b/src/game/g_syscalls.c @@ -147,6 +147,11 @@ void trap_GetConfigstring( int num, char *buffer, int bufferSize ) syscall( G_GET_CONFIGSTRING, num, buffer, bufferSize ); } +void trap_SetConfigstringRestrictions( int num, const clientList_t *clientList ) +{ + syscall( G_SET_CONFIGSTRING_RESTRICTIONS, num, clientList ); +} + void trap_GetUserinfo( int num, char *buffer, int bufferSize ) { syscall( G_GET_USERINFO, num, buffer, bufferSize ); diff --git a/src/game/g_team.c b/src/game/g_team.c index 7384b4b1..6a528b4f 100644 --- a/src/game/g_team.c +++ b/src/game/g_team.c @@ -80,6 +80,62 @@ qboolean OnSameTeam( gentity_t *ent1, gentity_t *ent2 ) /* ================== +G_ClientListForTeam +================== +*/ +static clientList_t G_ClientListForTeam( team_t team ) +{ + int i; + clientList_t clientList; + + Com_Memset( &clientList, 0, sizeof( clientList_t ) ); + + for( i = 0; i < g_maxclients.integer; i++ ) + { + gentity_t *ent = g_entities + i; + if( ent->client->pers.connected != CON_CONNECTED ) + continue; + + if( ent->inuse && ( ent->client->ps.stats[ STAT_TEAM ] == team ) ) + Com_ClientListAdd( &clientList, ent->client->ps.clientNum ); + } + + return clientList; +} + +/* +================== +G_UpdateTeamConfigStrings +================== +*/ +static void G_UpdateTeamConfigStrings( void ) +{ + clientList_t alienTeam = G_ClientListForTeam( TEAM_ALIENS ); + clientList_t humanTeam = G_ClientListForTeam( TEAM_HUMANS ); + + if( level.intermissiontime ) + { + // No restrictions once the game has ended + Com_Memset( &alienTeam, 0, sizeof( clientList_t ) ); + Com_Memset( &humanTeam, 0, sizeof( clientList_t ) ); + } + + trap_SetConfigstringRestrictions( CS_VOTE_TIME + TEAM_ALIENS, &humanTeam ); + trap_SetConfigstringRestrictions( CS_VOTE_STRING + TEAM_ALIENS, &humanTeam ); + trap_SetConfigstringRestrictions( CS_VOTE_YES + TEAM_ALIENS, &humanTeam ); + trap_SetConfigstringRestrictions( CS_VOTE_NO + TEAM_ALIENS, &humanTeam ); + + trap_SetConfigstringRestrictions( CS_VOTE_TIME + TEAM_HUMANS, &alienTeam ); + trap_SetConfigstringRestrictions( CS_VOTE_STRING + TEAM_HUMANS, &alienTeam ); + trap_SetConfigstringRestrictions( CS_VOTE_YES + TEAM_HUMANS, &alienTeam ); + trap_SetConfigstringRestrictions( CS_VOTE_NO + TEAM_HUMANS, &alienTeam ); + + trap_SetConfigstringRestrictions( CS_ALIEN_STAGES, &humanTeam ); + trap_SetConfigstringRestrictions( CS_HUMAN_STAGES, &alienTeam ); +} + +/* +================== G_LeaveTeam ================== */ @@ -163,6 +219,8 @@ void G_ChangeTeam( gentity_t *ent, team_t newTeam ) ClientUserinfoChanged( ent->client->ps.clientNum ); + G_UpdateTeamConfigStrings( ); + if( oldTeam != TEAM_NONE && newTeam != TEAM_NONE ) { G_LogPrintf( diff --git a/src/qcommon/q_shared.c b/src/qcommon/q_shared.c index 07e3669c..5b74badd 100644 --- a/src/qcommon/q_shared.c +++ b/src/qcommon/q_shared.c @@ -1403,3 +1403,82 @@ char *Com_SkipTokens( char *s, int numTokens, char *sep ) else return s; } + +/* +============ +Com_ClientListContains +============ +*/ +qboolean Com_ClientListContains( const clientList_t *list, int clientNum ) +{ + if( clientNum < 0 || clientNum >= MAX_CLIENTS || !list ) + return qfalse; + if( clientNum < 32 ) + return ( ( list->lo & ( 1 << clientNum ) ) != 0 ); + else + return ( ( list->hi & ( 1 << ( clientNum - 32 ) ) ) != 0 ); +} + +/* +============ +Com_ClientListAdd +============ +*/ +void Com_ClientListAdd( clientList_t *list, int clientNum ) +{ + if( clientNum < 0 || clientNum >= MAX_CLIENTS || !list ) + return; + if( clientNum < 32 ) + list->lo |= ( 1 << clientNum ); + else + list->hi |= ( 1 << ( clientNum - 32 ) ); +} + +/* +============ +Com_ClientListRemove +============ +*/ +void Com_ClientListRemove( clientList_t *list, int clientNum ) +{ + if( clientNum < 0 || clientNum >= MAX_CLIENTS || !list ) + return; + if( clientNum < 32 ) + list->lo &= ~( 1 << clientNum ); + else + list->hi &= ~( 1 << ( clientNum - 32 ) ); +} + +/* +============ +Com_ClientListString +============ +*/ +char *Com_ClientListString( const clientList_t *list ) +{ + static char s[ 17 ]; + + s[ 0 ] = '\0'; + if( !list ) + return s; + Com_sprintf( s, sizeof( s ), "%08x%08x", list->hi, list->lo ); + return s; +} + +/* +============ +Com_ClientListParse +============ +*/ +void Com_ClientListParse( clientList_t *list, const char *s ) +{ + if( !list ) + return; + list->lo = 0; + list->hi = 0; + if( !s ) + return; + if( strlen( s ) != 16 ) + return; + sscanf( s, "%x%x", &list->hi, &list->lo ); +} diff --git a/src/qcommon/q_shared.h b/src/qcommon/q_shared.h index 64acc8d0..5aaf0878 100644 --- a/src/qcommon/q_shared.h +++ b/src/qcommon/q_shared.h @@ -739,6 +739,18 @@ char *Com_SkipCharset( char *s, char *sep ); void Com_RandomBytes( byte *string, int len ); +typedef struct +{ + unsigned int hi; + unsigned int lo; +} clientList_t; + +qboolean Com_ClientListContains( const clientList_t *list, int clientNum ); +void Com_ClientListAdd( clientList_t *list, int clientNum ); +void Com_ClientListRemove( clientList_t *list, int clientNum ); +char *Com_ClientListString( const clientList_t *list ); +void Com_ClientListParse( clientList_t *list, const char *s ); + // mode parm for FS_FOpenFile typedef enum { FS_READ, diff --git a/src/server/server.h b/src/server/server.h index fe78026c..fca29aae 100644 --- a/src/server/server.h +++ b/src/server/server.h @@ -64,6 +64,13 @@ typedef enum { SS_GAME // actively running } serverState_t; +typedef struct configString_s { + char *s; + + qboolean restricted; // if true, don't send to clientList + clientList_t clientList; +} configString_t; + typedef struct { serverState_t state; qboolean restarting; // if true, send configstring changes during SS_LOADING @@ -77,7 +84,7 @@ typedef struct { int timeResidual; // <= 1000 / sv_frame->value int nextFrameTime; // when time > nextFrameTime, process world struct cmodel_s *models[MAX_MODELS]; - char *configstrings[MAX_CONFIGSTRINGS]; + configString_t configstrings[MAX_CONFIGSTRINGS]; svEntity_t svEntities[MAX_GENTITIES]; char *entityParsePoint; // used during game VM init @@ -301,6 +308,7 @@ void SV_MasterGameStat( const char *data ); // void SV_SetConfigstring( int index, const char *val ); void SV_GetConfigstring( int index, char *buffer, int bufferSize ); +void SV_SetConfigstringRestrictions(int index, const clientList_t* clientList); void SV_UpdateConfigstrings( client_t *client ); void SV_SetUserinfo( int index, const char *val ); diff --git a/src/server/sv_client.c b/src/server/sv_client.c index f164654c..319f865e 100644 --- a/src/server/sv_client.c +++ b/src/server/sv_client.c @@ -440,10 +440,10 @@ static void SV_SendClientGameState( client_t *client ) { // write the configstrings for ( start = 0 ; start < MAX_CONFIGSTRINGS ; start++ ) { - if (sv.configstrings[start][0]) { + if (sv.configstrings[start].s[0]) { MSG_WriteByte( &msg, svc_configstring ); MSG_WriteShort( &msg, start ); - MSG_WriteBigString( &msg, sv.configstrings[start] ); + MSG_WriteBigString( &msg, sv.configstrings[start].s ); } } diff --git a/src/server/sv_game.c b/src/server/sv_game.c index 1efa6d5f..2db7ee3f 100644 --- a/src/server/sv_game.c +++ b/src/server/sv_game.c @@ -386,6 +386,9 @@ intptr_t SV_GameSystemCalls( intptr_t *args ) { case G_GET_CONFIGSTRING: SV_GetConfigstring( args[1], VMA(2), args[3] ); return 0; + case G_SET_CONFIGSTRING_RESTRICTIONS: + SV_SetConfigstringRestrictions( args[1], VMA(2) ); + return 0; case G_SET_USERINFO: SV_SetUserinfo( args[1], VMA(2) ); return 0; diff --git a/src/server/sv_init.c b/src/server/sv_init.c index 34ced5c5..0de275ce 100644 --- a/src/server/sv_init.c +++ b/src/server/sv_init.c @@ -37,7 +37,14 @@ static void SV_SendConfigstring(client_t *client, int index) int maxChunkSize = MAX_STRING_CHARS - 24; int len; - len = strlen(sv.configstrings[index]); + if( sv.configstrings[index].restricted && Com_ClientListContains( + &sv.configstrings[index].clientList, client->gentity->s.number ) ) { + // Send a blank config string for this client if it's listed + SV_SendServerCommand( client, "cs %i \"\"\n", index ); + return; + } + + len = strlen(sv.configstrings[index].s); if( len >= maxChunkSize ) { int sent = 0; @@ -55,7 +62,7 @@ static void SV_SendConfigstring(client_t *client, int index) else { cmd = "bcs1"; } - Q_strncpyz( buf, &sv.configstrings[index][sent], + Q_strncpyz( buf, &sv.configstrings[index].s[sent], maxChunkSize ); SV_SendServerCommand( client, "%s %i \"%s\"\n", cmd, @@ -67,7 +74,7 @@ static void SV_SendConfigstring(client_t *client, int index) } else { // standard cs, just send it SV_SendServerCommand( client, "cs %i \"%s\"\n", index, - sv.configstrings[index] ); + sv.configstrings[index].s ); } } @@ -117,13 +124,13 @@ void SV_SetConfigstring (int index, const char *val) { } // don't bother broadcasting an update if no change - if ( !strcmp( val, sv.configstrings[ index ] ) ) { + if ( !strcmp( val, sv.configstrings[ index ].s ) ) { return; } // change the string in sv - Z_Free( sv.configstrings[index] ); - sv.configstrings[index] = CopyString( val ); + Z_Free( sv.configstrings[index].s ); + sv.configstrings[index].s = CopyString( val ); // send it to all the clients if we aren't // spawning a new server @@ -159,12 +166,35 @@ void SV_GetConfigstring( int index, char *buffer, int bufferSize ) { if ( index < 0 || index >= MAX_CONFIGSTRINGS ) { Com_Error (ERR_DROP, "SV_GetConfigstring: bad index %i\n", index); } - if ( !sv.configstrings[index] ) { + if ( !sv.configstrings[index].s ) { buffer[0] = 0; return; } - Q_strncpyz( buffer, sv.configstrings[index], bufferSize ); + Q_strncpyz( buffer, sv.configstrings[index].s, bufferSize ); +} + +/* +=============== +SV_SetConfigstringRestrictions +=============== +*/ +void SV_SetConfigstringRestrictions (int index, const clientList_t* clientList) { + int i; + clientList_t oldClientList = sv.configstrings[index].clientList; + + sv.configstrings[index].clientList = *clientList; + sv.configstrings[index].restricted = qtrue; + + for ( i = 0 ; i < sv_maxclients->integer ; i++ ) { + if ( svs.clients[i].state >= CS_CONNECTED ) { + if ( Com_ClientListContains( &oldClientList, i ) != + Com_ClientListContains( clientList, i ) ) { + // A client has left or joined the restricted list, so update + SV_SendConfigstring(&svs.clients[i], index); + } + } + } } @@ -366,8 +396,8 @@ static void SV_ClearServer(void) { int i; for ( i = 0 ; i < MAX_CONFIGSTRINGS ; i++ ) { - if ( sv.configstrings[i] ) { - Z_Free( sv.configstrings[i] ); + if ( sv.configstrings[i].s ) { + Z_Free( sv.configstrings[i].s ); } } Com_Memset (&sv, 0, sizeof(sv)); @@ -461,7 +491,9 @@ void SV_SpawnServer( char *server, qboolean killBots ) { // wipe the entire per-level structure SV_ClearServer(); for ( i = 0 ; i < MAX_CONFIGSTRINGS ; i++ ) { - sv.configstrings[i] = CopyString(""); + sv.configstrings[i].s = CopyString(""); + sv.configstrings[i].restricted = qfalse; + Com_Memset(&sv.configstrings[i].clientList, 0, sizeof(clientList_t)); } // make sure we are not paused diff --git a/src/ui/ui_main.c b/src/ui/ui_main.c index f148b8c1..83092c72 100644 --- a/src/ui/ui_main.c +++ b/src/ui/ui_main.c @@ -1838,7 +1838,7 @@ static void UI_BuildPlayerList( void ) if( info[0] ) { - BG_ClientListParse( &uiInfo.ignoreList[ uiInfo.playerCount ], + Com_ClientListParse( &uiInfo.ignoreList[ uiInfo.playerCount ], Info_ValueForKey( info, "ig" ) ); Q_strncpyz( uiInfo.rawPlayerNames[uiInfo.playerCount], Info_ValueForKey( info, "n" ), MAX_NAME_LENGTH ); @@ -3277,17 +3277,17 @@ static void UI_RunMenuScript( char **args ) { if( uiInfo.ignoreIndex >= 0 && uiInfo.ignoreIndex < uiInfo.playerCount ) { - if( BG_ClientListTest( &uiInfo.ignoreList[ uiInfo.myPlayerIndex ], + if( Com_ClientListContains( &uiInfo.ignoreList[ uiInfo.myPlayerIndex ], uiInfo.clientNums[ uiInfo.ignoreIndex ] ) ) { - BG_ClientListRemove( &uiInfo.ignoreList[ uiInfo.myPlayerIndex ], + Com_ClientListRemove( &uiInfo.ignoreList[ uiInfo.myPlayerIndex ], uiInfo.clientNums[ uiInfo.ignoreIndex ] ); trap_Cmd_ExecuteText( EXEC_APPEND, va( "unignore %i\n", uiInfo.clientNums[ uiInfo.ignoreIndex ] ) ); } else { - BG_ClientListAdd( &uiInfo.ignoreList[ uiInfo.myPlayerIndex ], + Com_ClientListAdd( &uiInfo.ignoreList[ uiInfo.myPlayerIndex ], uiInfo.clientNums[ uiInfo.ignoreIndex ] ); trap_Cmd_ExecuteText( EXEC_APPEND, va( "ignore %i\n", uiInfo.clientNums[ uiInfo.ignoreIndex ] ) ); @@ -3298,10 +3298,10 @@ static void UI_RunMenuScript( char **args ) { if( uiInfo.ignoreIndex >= 0 && uiInfo.ignoreIndex < uiInfo.playerCount ) { - if( !BG_ClientListTest( &uiInfo.ignoreList[ uiInfo.myPlayerIndex ], + if( !Com_ClientListContains( &uiInfo.ignoreList[ uiInfo.myPlayerIndex ], uiInfo.clientNums[ uiInfo.ignoreIndex ] ) ) { - BG_ClientListAdd( &uiInfo.ignoreList[ uiInfo.myPlayerIndex ], + Com_ClientListAdd( &uiInfo.ignoreList[ uiInfo.myPlayerIndex ], uiInfo.clientNums[ uiInfo.ignoreIndex ] ); trap_Cmd_ExecuteText( EXEC_APPEND, va( "ignore %i\n", uiInfo.clientNums[ uiInfo.ignoreIndex ] ) ); @@ -3312,10 +3312,10 @@ static void UI_RunMenuScript( char **args ) { if( uiInfo.ignoreIndex >= 0 && uiInfo.ignoreIndex < uiInfo.playerCount ) { - if( BG_ClientListTest( &uiInfo.ignoreList[ uiInfo.myPlayerIndex ], + if( Com_ClientListContains( &uiInfo.ignoreList[ uiInfo.myPlayerIndex ], uiInfo.clientNums[ uiInfo.ignoreIndex ] ) ) { - BG_ClientListRemove( &uiInfo.ignoreList[ uiInfo.myPlayerIndex ], + Com_ClientListRemove( &uiInfo.ignoreList[ uiInfo.myPlayerIndex ], uiInfo.clientNums[ uiInfo.ignoreIndex ] ); trap_Cmd_ExecuteText( EXEC_APPEND, va( "unignore %i\n", uiInfo.clientNums[ uiInfo.ignoreIndex ] ) ); @@ -3539,12 +3539,12 @@ static const char *UI_FeederItemText( float feederID, int index, int column, qha { case 1: // am I ignoring him - return ( BG_ClientListTest( &uiInfo.ignoreList[ uiInfo.myPlayerIndex ], + return ( Com_ClientListContains( &uiInfo.ignoreList[ uiInfo.myPlayerIndex ], uiInfo.clientNums[ index ] ) ) ? "X" : ""; case 2: // is he ignoring me - return ( BG_ClientListTest( &uiInfo.ignoreList[ index ], + return ( Com_ClientListContains( &uiInfo.ignoreList[ index ], uiInfo.playerNumber ) ) ? "X" : ""; default: |