summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/game/g_admin.c192
-rw-r--r--src/game/g_admin.h14
-rw-r--r--src/game/g_local.h3
-rw-r--r--src/game/g_main.c8
-rw-r--r--src/game/g_svcmds.c28
5 files changed, 243 insertions, 2 deletions
diff --git a/src/game/g_admin.c b/src/game/g_admin.c
index 99a08e5..05fcd2b 100644
--- a/src/game/g_admin.c
+++ b/src/game/g_admin.c
@@ -72,6 +72,11 @@ g_admin_cmd_t g_admin_cmds[ ] =
""
},
+ {"sm", G_admin_sm, "schachtmeister",
+ "Schachtmeister",
+ "..."
+ },
+
{"ban", G_admin_ban, "ban",
"ban a player by IP and GUID with an optional expiration time and reason."
" time is specified as numbers followed by units 'w' (weeks), 'd' "
@@ -1852,11 +1857,49 @@ void G_admin_namelog_cleanup( )
for( i = 0; i < MAX_ADMIN_NAMELOGS && g_admin_namelog[ i ]; i++ )
{
+ if( g_admin_namelog[ i ]->smj.comment )
+ G_Free( g_admin_namelog[ i ]->smj.comment );
G_Free( g_admin_namelog[ i ] );
g_admin_namelog[ i ] = NULL;
}
}
+static void dispatchSchachtmeisterIPAQuery( const char *ipa )
+{
+ trap_SendConsoleCommand( EXEC_APPEND, va( "smq ipa \"%s\"\n", ipa ) );
+}
+
+static void schachtmeisterProcess( g_admin_namelog_t *namelog )
+{
+ schachtmeisterJudgement_t *j = &namelog->smj;
+
+ if( !j->ratingTime || level.time - j->ratingTime >= 600000 )
+ {
+ if( j->queryTime )
+ return;
+
+ j->queryTime = level.time;
+ goto dispatch;
+ }
+
+ if( !j->queryTime || level.time - j->queryTime >= 60000 )
+ return;
+
+ if( j->dispatchTime && level.time - j->dispatchTime < 5000 )
+ return;
+
+ dispatch:
+ j->dispatchTime = level.time;
+ dispatchSchachtmeisterIPAQuery( namelog->ip );
+}
+
+void G_admin_schachtmeisterFrame( void )
+{
+ int i;
+ for( i = 0; i < MAX_ADMIN_NAMELOGS && g_admin_namelog[ i ]; i++ )
+ schachtmeisterProcess( g_admin_namelog[ i ] );
+}
+
void G_admin_namelog_update( gclient_t *client, qboolean disconnect )
{
int i, j;
@@ -1981,6 +2024,7 @@ void G_admin_namelog_update( gclient_t *client, qboolean disconnect )
Q_strncpyz( namelog->name[ 0 ], client->pers.netname,
sizeof( namelog->name[ 0 ] ) );
namelog->slot = ( disconnect ) ? -1 : clientNum;
+ schachtmeisterProcess( namelog );
g_admin_namelog[ i ] = namelog;
}
@@ -3022,6 +3066,69 @@ qboolean G_admin_setdevmode( gentity_t *ent, int skiparg )
return qtrue;
}
+qboolean G_admin_sm( gentity_t *ent, int skiparg )
+{
+ const char *s;
+ char feature[ 16 ];
+
+ if( G_SayArgc() < 2 + skiparg )
+ {
+ usage:
+ ADMP( "^3!sm: ^7usage: !sm ipa <IPA>\n" );
+ return qfalse;
+ }
+
+ s = G_SayConcatArgs( 1 + skiparg );
+ if( strchr( s, '\n' ) || strchr( s, '\r' ) )
+ {
+ ADMP( "^3!sm: ^7invalid character\n" );
+ return qfalse;
+ }
+
+ G_SayArgv( 1 + skiparg, feature, sizeof( feature ) );
+
+ if( !Q_stricmp( feature, "ipa" ) )
+ {
+ char ipa[ 32 ];
+ int parts[ 4 ];
+
+ if( G_SayArgc() > 3 + skiparg )
+ {
+ ADMP( "^3!sm: ^7excessive arguments\n" );
+ goto usage;
+ }
+ G_SayArgv( 2 + skiparg, ipa, sizeof( ipa ) );
+
+ // have a well-formed IPv4 address, because Schachtmeister silently drops all invalid requests
+
+ if( sscanf( ipa, "%i.%i.%i.%i", &parts[0], &parts[1], &parts[2], &parts[3] ) != 4
+ || parts[0] < 0 || parts[0] > 255
+ || parts[1] < 0 || parts[1] > 255
+ || parts[2] < 0 || parts[2] > 255
+ || parts[3] < 0 || parts[3] > 255 )
+ {
+ ADMP( "^3!sm: ^7invalid IP address\n" );
+ return qfalse;
+ }
+
+ snprintf( ipa, sizeof( ipa ), "%i.%i.%i.%i", parts[0], parts[1], parts[2], parts[3] );
+
+ if( rand() % 2 /* FIXME cache hit */ )
+ {
+ const char *answer = "interesting";
+ ADMP( va( "^3!sm: ^7IP address %s is: %s\n", ipa, answer ) );
+ return qtrue;
+ }
+
+ ADMP( "^3!sm: ^7hmm...\n" );
+ trap_SendConsoleCommand( EXEC_APPEND, va( "smq ipa \"%s\"\n", ipa ) );
+ }
+ else
+ goto usage;
+
+ return qtrue;
+}
+
qboolean G_admin_kick( gentity_t *ent, int skiparg )
{
int pids[ MAX_CLIENTS ];
@@ -3309,6 +3416,35 @@ qboolean G_admin_ban( gentity_t *ent, int skiparg )
return qtrue;
}
+void G_admin_IPA_judgement( const char *ipa, int rating, const char *comment )
+{
+ int i;
+ for( i = 0; i < MAX_ADMIN_NAMELOGS && g_admin_namelog[ i ]; i++ )
+ {
+ if( !strcmp( g_admin_namelog[ i ]->ip, ipa ) )
+ {
+ schachtmeisterJudgement_t *j = &g_admin_namelog[ i ]->smj;
+
+ j->ratingTime = level.time;
+ j->queryTime = 0;
+ j->dispatchTime = 0;
+
+ j->rating = rating;
+
+ if( j->comment )
+ G_Free( j->comment );
+
+ if( comment )
+ {
+ j->comment = G_Alloc( strlen( comment ) + 1 );
+ strcpy( j->comment, comment );
+ }
+ else
+ j->comment = NULL;
+ }
+ }
+}
+
qboolean G_admin_adjustban( gentity_t *ent, int skiparg )
{
int bnum;
@@ -6753,6 +6889,56 @@ qboolean G_admin_nextmap( gentity_t *ent, int skiparg )
return qtrue;
}
+const char *displaySchachtmeisterJudgement( const schachtmeisterJudgement_t *j )
+{
+ char pc, ps;
+ static char display[ MAX_STRING_CHARS ];
+
+ if( j->queryTime )
+ {
+ if( level.time - j->queryTime >= 60000 )
+ pc = '0', ps = 'X'; // dead, apparently
+ else if( level.time - j->queryTime >= 10000 )
+ pc = '4', ps = 'z'; // asleep, apparently
+ else
+ pc = '5', ps = ','; // wait
+ }
+ else
+ pc = '7', ps = ' '; // stfu, compiler
+
+ if( j->ratingTime )
+ {
+ char rc, rs;
+
+ if( j->rating >= g_schachtmeisterClearThreshold.integer )
+ rc = '2', rs = 'o';
+ else if( j->rating <= g_schachtmeisterAutobahnThreshold.integer )
+ rc = '1', rs = '!';
+ else
+ rc = '3', rs = '?';
+
+ if( j->queryTime )
+ Com_sprintf( display, sizeof( display ), "^%c%c^%c%c ^%c% 4i", rc, rs, pc, ps, rc, j->rating );
+ else
+ Com_sprintf( display, sizeof( display ), "^%c%c % 4i", rc, rs, j->rating );
+
+ if( j->comment )
+ {
+ int l = strlen( display );
+ Com_sprintf( display + l, sizeof( display ) - l, " (%s)", j->comment );
+ }
+ }
+ else
+ {
+ if( j->queryTime )
+ Com_sprintf( display, sizeof( display ), " ^%c%c", pc, ps );
+ else // shouldn't happen
+ display[ 0 ] = '\0';
+ }
+
+ return display;
+}
+
qboolean G_admin_namelog( gentity_t *ent, int skiparg )
{
int i, j;
@@ -6793,10 +6979,11 @@ qboolean G_admin_namelog( gentity_t *ent, int skiparg )
guid_stub[ j ] = '\0';
if( g_admin_namelog[ i ]->slot > -1 )
ADMBP( "^3" );
- ADMBP( va( "%-2s (*%s) %15s^7",
+ ADMBP( va( "%-2s (*%s) %15s %s^7",
(g_admin_namelog[ i ]->slot > -1 ) ?
va( "%d", g_admin_namelog[ i ]->slot ) : "-",
- guid_stub, g_admin_namelog[ i ]->ip ) );
+ guid_stub, g_admin_namelog[ i ]->ip,
+ displaySchachtmeisterJudgement( &g_admin_namelog[ i ]->smj ) ) );
for( j = 0; j < MAX_ADMIN_NAMELOG_NAMES &&
g_admin_namelog[ i ]->name[ j ][ 0 ]; j++ )
{
@@ -10027,3 +10214,4 @@ qboolean G_admin_give(gentity_t *ent, int skiparg)
return qtrue;
}
+
diff --git a/src/game/g_admin.h b/src/game/g_admin.h
index 93458b6..b6ed952 100644
--- a/src/game/g_admin.h
+++ b/src/game/g_admin.h
@@ -168,6 +168,15 @@ typedef struct g_admin_command
}
g_admin_command_t;
+typedef struct
+{
+ int ratingTime;
+ int queryTime;
+ int dispatchTime;
+ int rating;
+ char *comment;
+} schachtmeisterJudgement_t;
+
typedef struct g_admin_namelog
{
char name[ MAX_ADMIN_NAMELOG_NAMES ][MAX_NAME_LENGTH ];
@@ -181,6 +190,7 @@ typedef struct g_admin_namelog
int denyHumanWeapons;
int denyAlienClasses;
int specExpires;
+ schachtmeisterJudgement_t smj;
}
g_admin_namelog_t;
@@ -255,6 +265,7 @@ qboolean G_admin_readconfig( gentity_t *ent, int skiparg );
qboolean G_admin_permission( gentity_t *ent, const char *flag );
qboolean G_admin_name_check( gentity_t *ent, char *name, char *err, int len );
void G_admin_namelog_update( gclient_t *ent, qboolean disconnect );
+void G_admin_IPA_judgement( const char *ipa, int rating, const char *comment );
void G_admin_maplog_result( char *flag );
int G_admin_level( gentity_t *ent );
void G_admin_set_adminname( gentity_t *ent );
@@ -269,6 +280,7 @@ void G_admin_chat_update( gentity_t *ent, int chan );
qboolean G_admin_time( gentity_t *ent, int skiparg );
qboolean G_admin_setlevel( gentity_t *ent, int skiparg );
qboolean G_admin_setdevmode( gentity_t *ent, int skiparg );
+qboolean G_admin_sm( gentity_t *ent, int skiparg );
qboolean G_admin_kick( gentity_t *ent, int skiparg );
qboolean G_admin_adjustban( gentity_t *ent, int skiparg );
qboolean G_admin_subnetban( gentity_t *ent, int skiparg );
@@ -361,4 +373,6 @@ void G_admin_namelog_cleanup( void );
void G_admin_report_check( int clientNum );
+void G_admin_schachtmeisterFrame( void );
+
#endif /* ifndef _G_ADMIN_H */
diff --git a/src/game/g_local.h b/src/game/g_local.h
index 6e077bd..550803a 100644
--- a/src/game/g_local.h
+++ b/src/game/g_local.h
@@ -1540,6 +1540,9 @@ extern vmCvar_t g_maxUnregReports;
extern vmCvar_t g_reportWelcomeComment;
+extern vmCvar_t g_schachtmeisterClearThreshold;
+extern vmCvar_t g_schachtmeisterAutobahnThreshold;
+
extern vmCvar_t g_scrimMode;
extern vmCvar_t g_revertCooldownTime;
diff --git a/src/game/g_main.c b/src/game/g_main.c
index 5cfc383..5fe4307 100644
--- a/src/game/g_main.c
+++ b/src/game/g_main.c
@@ -280,6 +280,9 @@ vmCvar_t g_maxUnregReports;
vmCvar_t g_reportWelcomeComment;
+vmCvar_t g_schachtmeisterClearThreshold;
+vmCvar_t g_schachtmeisterAutobahnThreshold;
+
vmCvar_t g_scrimMode;
vmCvar_t g_revertCooldownTime;
@@ -545,6 +548,9 @@ static cvarTable_t gameCvarTable[ ] =
{ &g_scrimMode, "g_scrimMode", "0", CVAR_ARCHIVE, 0, qfalse },
+ { &g_schachtmeisterClearThreshold, "g_schachtmeisterClearThreshold", "0", CVAR_ARCHIVE, 0, qfalse },
+ { &g_schachtmeisterAutobahnThreshold, "g_schachtmeisterAutobahnThreshold", "-50", CVAR_ARCHIVE, 0, qfalse },
+
{ &g_revertCooldownTime, "g_revertCooldownTime", "30", CVAR_ARCHIVE, 0, qfalse }
};
@@ -3488,6 +3494,8 @@ void G_RunFrame( int levelTime )
CheckTeamVote( PTE_HUMANS );
CheckTeamVote( PTE_ALIENS );
+ G_admin_schachtmeisterFrame();
+
// for tracking changes
CheckCvars( );
diff --git a/src/game/g_svcmds.c b/src/game/g_svcmds.c
index 8b7b575..c4ce182 100644
--- a/src/game/g_svcmds.c
+++ b/src/game/g_svcmds.c
@@ -704,6 +704,34 @@ qboolean ConsoleCommand( void )
return qtrue;
}
+ if( !Q_stricmp( cmd, "smr" ) )
+ {
+ if( trap_Argc() >= 2 )
+ {
+ char arg[ 32 ];
+ trap_Argv( 1, arg, sizeof( arg ) );
+
+ if( !Q_stricmp( arg, "ipa" ) && trap_Argc() >= 4 )
+ {
+ int rating;
+ const char *comment = NULL;
+
+ trap_Argv( 3, arg, sizeof( arg ) );
+ rating = atoi( arg );
+ if( trap_Argc() >= 5 )
+ comment = ConcatArgs( 4 );
+ trap_Argv( 2, arg, sizeof( arg ) );
+
+ G_admin_IPA_judgement( arg, rating, comment );
+
+ return qtrue;
+ }
+ }
+
+ G_Printf( "unrecognized Schachtmeister response: %s\n", ConcatArgs( 1 ) );
+ return qtrue;
+ }
+
// see if this is a a admin command
if( G_admin_cmd_check( NULL, qfalse ) )
return qtrue;