diff --git a/engine/server/server.h b/engine/server/server.h index 2e7a2d37..66879c90 100644 --- a/engine/server/server.h +++ b/engine/server/server.h @@ -80,6 +80,8 @@ extern int SV_UPDATE_BACKUP; #define FCL_SEND_RESOURCES BIT( 9 ) #define FCL_FORCE_UNMODIFIED BIT( 10 ) +#define MAX_CLIENT_IGNORECMDTIME_WARNS 10 // just a random number (for now) + typedef enum { ss_dead, // no map loaded @@ -258,6 +260,9 @@ typedef struct sv_client_s int userid; // identifying number on server int extensions; char useragent[MAX_INFO_STRING]; + + int ignorecmdtime_warns; // how many times client time was faster than server during this session + qboolean ignorecmdtime_warned; // did we warn our server operator in the log for this batch of commands? } sv_client_t; /* @@ -443,6 +448,7 @@ extern convar_t coop; extern convar_t sv_cheats; extern convar_t public_server; extern convar_t sv_nat; +extern convar_t sv_speedhack_kick; extern convar_t *sv_pausable; // allows pause in multiplayer extern convar_t *sv_check_errors; diff --git a/engine/server/sv_main.c b/engine/server/sv_main.c index 59923634..66570fa4 100644 --- a/engine/server/sv_main.c +++ b/engine/server/sv_main.c @@ -59,6 +59,7 @@ CVAR_DEFINE_AUTO( sv_log_onefile, "0", FCVAR_ARCHIVE, "logs server information t CVAR_DEFINE_AUTO( sv_trace_messages, "0", FCVAR_LATCH, "enable server usermessages tracing (good for developers)" ); CVAR_DEFINE_AUTO( sv_master_response_timeout, "4", FCVAR_ARCHIVE, "master server heartbeat response timeout in seconds" ); CVAR_DEFINE_AUTO( sv_autosave, "1", FCVAR_ARCHIVE|FCVAR_SERVER|FCVAR_PRIVILEGED, "enable autosaving" ); +CVAR_DEFINE_AUTO( sv_speedhack_kick, "1", FCVAR_ARCHIVE, "enable automatic kicking players who use speedhacks" ); // game-related cvars CVAR_DEFINE_AUTO( mapcyclefile, "mapcycle.txt", 0, "name of multiplayer map cycle configuration file" ); @@ -919,6 +920,8 @@ void SV_Init( void ) Cvar_RegisterVariable( &sv_enttools_enable ); Cvar_RegisterVariable( &sv_enttools_maxfire ); + Cvar_RegisterVariable( &sv_speedhack_kick ); + sv_allow_joystick = Cvar_Get( "sv_allow_joystick", "1", FCVAR_ARCHIVE, "allow connect with joystick enabled" ); sv_allow_mouse = Cvar_Get( "sv_allow_mouse", "1", FCVAR_ARCHIVE, "allow connect with mouse" ); sv_allow_touch = Cvar_Get( "sv_allow_touch", "1", FCVAR_ARCHIVE, "allow connect with touch controls" ); diff --git a/engine/server/sv_pmove.c b/engine/server/sv_pmove.c index 6770b5c4..59e9b66a 100644 --- a/engine/server/sv_pmove.c +++ b/engine/server/sv_pmove.c @@ -911,11 +911,23 @@ void SV_RunCmd( sv_client_t *cl, usercmd_t *ucmd, int random_seed ) if( cl->ignorecmdtime > host.realtime ) { + if( !cl->ignorecmdtime_warned ) + { + // report to server op + Con_Reportf( S_WARN "%s time is faster than server time (speed hack?)\n", cl->name ); + cl->ignorecmdtime_warned = true; + cl->ignorecmdtime_warns++; + + // automatically kick player + if( sv_speedhack_kick.value && cl->ignorecmdtime_warns > MAX_CLIENT_IGNORECMDTIME_WARNS ) + SV_KickPlayer( cl, "Speed hacks aren't allowed on this server" ); + } cl->cmdtime += ((double)ucmd->msec / 1000.0 ); return; } cl->ignorecmdtime = 0.0; + cl->ignorecmdtime_warned = false; // chop up very long commands if( cmd.msec > 50 )