diff options
| author | /dev/humancontroller <devhc@example.com> | 2017-04-15 00:16:35 +0200 | 
|---|---|---|
| committer | /dev/humancontroller <devhc@example.com> | 2017-04-15 17:29:37 +0200 | 
| commit | 259c996ebe14cdb52e4a47149ce6c33dbeffa4d3 (patch) | |
| tree | 9821fb451b7a7fc280a5446b479c5b8b756fab38 | |
| parent | 91c463d4bfe3e57330e5fbce63c98eb22d5b208e (diff) | |
implement Schachtmeister v2
| -rw-r--r-- | src/game/g_admin.c | 192 | ||||
| -rw-r--r-- | src/game/g_admin.h | 14 | ||||
| -rw-r--r-- | src/game/g_local.h | 3 | ||||
| -rw-r--r-- | src/game/g_main.c | 8 | ||||
| -rw-r--r-- | src/game/g_svcmds.c | 28 | 
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;  | 
