summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/cgame/cg_main.c10
-rw-r--r--src/cgame/cg_players.c2
-rw-r--r--src/cgame/cg_servercmds.c65
-rw-r--r--src/game/bg_misc.c79
-rw-r--r--src/game/bg_public.h14
-rw-r--r--src/game/g_client.c4
-rw-r--r--src/game/g_cmds.c12
-rw-r--r--src/game/g_local.h1
-rw-r--r--src/game/g_main.c26
-rw-r--r--src/game/g_public.h2
-rw-r--r--src/game/g_session.c4
-rw-r--r--src/game/g_syscalls.asm119
-rw-r--r--src/game/g_syscalls.c5
-rw-r--r--src/game/g_team.c58
-rw-r--r--src/qcommon/q_shared.c79
-rw-r--r--src/qcommon/q_shared.h12
-rw-r--r--src/server/server.h10
-rw-r--r--src/server/sv_client.c4
-rw-r--r--src/server/sv_game.c3
-rw-r--r--src/server/sv_init.c54
-rw-r--r--src/ui/ui_main.c20
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: