diff options
-rw-r--r-- | src/game/g_admin.c | 6 | ||||
-rw-r--r-- | src/game/g_cmds.c | 38 | ||||
-rw-r--r-- | src/game/g_local.h | 7 | ||||
-rw-r--r-- | src/game/g_main.c | 6 |
4 files changed, 56 insertions, 1 deletions
diff --git a/src/game/g_admin.c b/src/game/g_admin.c index b7aae83e..e712dfeb 100644 --- a/src/game/g_admin.c +++ b/src/game/g_admin.c @@ -953,6 +953,9 @@ qboolean G_admin_cmd_check( gentity_t *ent, qboolean say ) if( admin_command_permission( ent, cmd ) ) { + // flooding say will have already been accounted for in ClientCommand + if( !say && G_FloodLimited( ent ) ) + return qtrue; trap_SendConsoleCommand( EXEC_APPEND, g_admin_commands[ i ]->exec ); admin_log( ent, cmd, skip ); } @@ -971,6 +974,9 @@ qboolean G_admin_cmd_check( gentity_t *ent, qboolean say ) if( G_admin_permission( ent, g_admin_cmds[ i ].flag[ 0 ] ) ) { + // flooding say will have already been accounted for in ClientCommand + if( !say && G_FloodLimited( ent ) ) + return qtrue; g_admin_cmds[ i ].handler( ent, skip ); admin_log( ent, cmd, skip ); } diff --git a/src/game/g_cmds.c b/src/game/g_cmds.c index 57b43c85..86a26483 100644 --- a/src/game/g_cmds.c +++ b/src/game/g_cmds.c @@ -3025,6 +3025,41 @@ void Cmd_Damage_f( gentity_t *ent ) ( nonloc ? DAMAGE_NO_LOCDAMAGE : 0 ), MOD_TARGET_LASER ); } +/* +================== +G_FloodLimited + +Determine whether a user is flood limited, and adjust their flood demerits +Notify them if this is the first time they were over the limit +================== +*/ +qboolean G_FloodLimited( gentity_t *ent ) +{ + int deltatime = level.time - ent->client->pers.floodTime; + int flooding; + + if( g_floodMinTime.integer <= 0 ) + return qfalse; + + if( G_admin_permission( ent, ADMF_NOCENSORFLOOD ) ) + return qfalse; + + ent->client->pers.floodDemerits += g_floodMinTime.integer - deltatime; + if( ent->client->pers.floodDemerits < 0 ) + ent->client->pers.floodDemerits = 0; + ent->client->pers.floodTime = level.time; + + flooding = ent->client->pers.floodDemerits - g_floodMaxDemerits.integer; + if( flooding <= 0 ) + return qfalse; + // seconds (rounded up) + flooding = ( flooding + 999 ) / 1000; + trap_SendServerCommand( ent - g_entities, va( "print \"You are flooding: " + "please wait %d second%s before trying again\n", + flooding, ( flooding != 1 ) ? "s" : "" ) ); + return qtrue; +} + commands_t cmds[ ] = { // normal commands { "team", 0, Cmd_Team_f }, @@ -3125,7 +3160,8 @@ void ClientCommand( int clientNum ) return; } - if( cmds[ i ].cmdFlags & CMD_MESSAGE && ent->client->pers.muted ) + if( cmds[ i ].cmdFlags & CMD_MESSAGE && ( ent->client->pers.muted || + G_FloodLimited( ent ) ) ) return; if( cmds[ i ].cmdFlags & CMD_TEAM && diff --git a/src/game/g_local.h b/src/game/g_local.h index bd5cdc78..da99d44e 100644 --- a/src/game/g_local.h +++ b/src/game/g_local.h @@ -330,6 +330,10 @@ typedef struct qboolean vote; qboolean teamVote; + // flood protection + int floodDemerits; + int floodTime; + vec3_t lastDeathLocation; char guid[ 33 ]; char ip[ 40 ]; @@ -1140,6 +1144,9 @@ extern vmCvar_t g_chatTeamPrefix; extern vmCvar_t g_debugVoices; extern vmCvar_t g_voiceChats; +extern vmCvar_t g_floodMaxDemerits; +extern vmCvar_t g_floodMinTime; + extern vmCvar_t g_shove; extern vmCvar_t g_mapConfigs; diff --git a/src/game/g_main.c b/src/game/g_main.c index 0c8aa33f..0a2cbedb 100644 --- a/src/game/g_main.c +++ b/src/game/g_main.c @@ -121,6 +121,9 @@ vmCvar_t g_shove; vmCvar_t g_mapConfigs; vmCvar_t g_chatTeamPrefix; +vmCvar_t g_floodMaxDemerits; +vmCvar_t g_floodMinTime; + vmCvar_t g_layouts; vmCvar_t g_layoutAuto; @@ -232,6 +235,9 @@ static cvarTable_t gameCvarTable[ ] = { &g_chatTeamPrefix, "g_chatTeamPrefix", "0", CVAR_ARCHIVE, 0, qfalse }, + { &g_floodMaxDemerits, "g_floodMaxDemerits", "5000", CVAR_ARCHIVE, 0, qfalse }, + { &g_floodMinTime, "g_floodMinTime", "2000", CVAR_ARCHIVE, 0, qfalse }, + { &g_markDeconstruct, "g_markDeconstruct", "1", CVAR_SERVERINFO | CVAR_ARCHIVE, 0, qfalse }, { &g_debugMapRotation, "g_debugMapRotation", "0", 0, 0, qfalse }, |