diff options
| -rw-r--r-- | src/game/g_admin.c | 1644 | ||||
| -rw-r--r-- | src/game/g_admin.h | 60 | ||||
| -rw-r--r-- | src/game/g_client.c | 3 | ||||
| -rw-r--r-- | src/game/g_cmds.c | 12 | ||||
| -rw-r--r-- | src/game/g_local.h | 6 | ||||
| -rw-r--r-- | src/game/g_main.c | 15 | 
6 files changed, 1699 insertions, 41 deletions
diff --git a/src/game/g_admin.c b/src/game/g_admin.c index 7bd4f0d..60779a7 100644 --- a/src/game/g_admin.c +++ b/src/game/g_admin.c @@ -273,48 +273,84 @@ g_admin_cmd_t g_admin_cmds[ ] =        "move a player to a specified team",        "[^3name|slot#^7] [^3h|a|s^7] (^3duration^7)"      }, - +     +    {"rarclist", G_admin_rarclist, "reportmanage", +      "display a (partial) list of archived reports", +      "[^3from id#|player|ip range^7]" +    }, +     +    {"rban", G_admin_rban, "reportmanage", +      "ban a reported player", +      "[^3report#^7] [^3time^7] [^3reason^7]" +    }, +     +    {"rclose", G_admin_rclose, "reportmanage", +      "closes a report entry, argument '!' archives it", +      "[^3report#^7] (^3!^7) [^3message^7]\n" +      "you must specify a message for the reporter to see" +    }, +          {"readconfig", G_admin_readconfig, "readconfig",        "reloads the admin config file and refreshes permission flags",        ""      }, +    {"report", G_admin_report, "report", +      "report a player - provide evidence if possible", +      "[^3name|slot#^7] [^3reason/additional info^7]" +    }, +          {"register", G_admin_register, "register",        "Registers your name to protect it from being used by others or updates your admin name to your current name.",        "[^3level^7] [^3password^7]"      }, - +          {"rename", G_admin_rename, "rename",        "rename a player",        "[^3name|slot#^7] [^3new name^7]"      }, - +          {"restart", G_admin_restart, "restart",        "restart the current map (optionally using named layout or keeping/switching teams)",        "(^5layout^7) (^5keepteams|switchteams|keepteamslock|switchteamslock^7)"      }, - +          {"revert", G_admin_revert, "revert",        "revert one or more buildlog events, optionally of only one team",        "(^5xnum^7) (^5#ID^7) (^5-name|num^7) (^5a|h^7)"        "\n ^3Example:^7 '!revert x5 h' reverts the last 5 events affecting human buildables"      }, - +     +    {"rlist", G_admin_rlist, "report", +      "display a (partial) list of active reports", +      "[^3from id#|player|ip range^7]" +    }, +     +    {"rnote", G_admin_rnote, "reportmanage", +      "edits the note of a report or archive entry", +      "[^3report#^7] (^3!^7) [^3note^7] - ^3!^7 means archive instead of report" +    }, +          {"rotation", G_admin_listrotation, "rotation",         "display a list of maps that are in the active map rotation",         ""      }, - +     +    {"rpurge", G_admin_rpurge, "reportpurge", +      "purges a report or archive entry", +      "[^3report#^7] (^3!^7) - ^3!^7 means archive instead of report" +    }, +          {"seen", G_admin_seen, "seen",        "find the last time a player was on the server",        "[^3name|admin#^7]"      }, - +          {"setlevel", G_admin_setlevel, "setlevel",        "sets the admin level of a player",        "[^3name|slot#|admin#^7] [^3level^7]"      }, - +          {"showbans", G_admin_showbans, "showbans",        "display a (partial) list of active bans",        "(^5start at ban#^7) (^5name|IP|'-subnet'^7)" @@ -411,6 +447,8 @@ static int admin_level_maxname = 0;  g_admin_level_t *g_admin_levels[ MAX_ADMIN_LEVELS ];  g_admin_admin_t *g_admin_admins[ MAX_ADMIN_ADMINS ];  g_admin_ban_t *g_admin_bans[ MAX_ADMIN_BANS ]; +g_admin_report_t *g_admin_reports[ MAX_ADMIN_REPORTS ]; +g_admin_archive_t *g_admin_archives[ MAX_ADMIN_ARCHIVES ];  g_admin_command_t *g_admin_commands[ MAX_ADMIN_COMMANDS ];  g_admin_namelog_t *g_admin_namelog[ MAX_ADMIN_NAMELOGS ]; @@ -735,6 +773,100 @@ static void admin_writeconfig( void )      trap_FS_Write( "\n", 1, f );    }    trap_FS_FCloseFile( f ); +   +  if( !g_report.string[ 0 ] ) +  { +    G_Printf( S_COLOR_YELLOW "WARNING: g_report is not set. " +      " configuration will not be saved to a file.\n" ); +    return; +  } +  t = trap_RealTime( NULL ); +  len = trap_FS_FOpenFile( g_report.string, &f, FS_WRITE ); +  if( len < 0 ) +  { +    G_Printf( "admin_writeconfig: could not open g_report file \"%s\"\n", +              g_report.string ); +    return; +  } +    for( i = 0; i < MAX_ADMIN_REPORTS && g_admin_reports[ i ]; i++ ) +  {   +    if( ( g_admin_reports[ i ]->expires != 0  && ( g_admin_reports[ i ]->expires - t ) < 1 ) || g_admin_reports[ i ]->closed == 2 ) +    {  +        continue; +    } +       +    trap_FS_Write( "[report]\n", 9, f ); +    trap_FS_Write( "name    = ", 10, f ); +    admin_writeconfig_string( g_admin_reports[ i ]->name, f ); +    trap_FS_Write( "guid    = ", 10, f ); +    admin_writeconfig_string( g_admin_reports[ i ]->guid, f ); +    trap_FS_Write( "ip      = ", 10, f ); +    admin_writeconfig_string( g_admin_reports[ i ]->ip, f ); +    trap_FS_Write( "reason  = ", 10, f ); +    admin_writeconfig_string( g_admin_reports[ i ]->reason, f ); +    trap_FS_Write( "map     = ", 10, f ); +    admin_writeconfig_string( g_admin_reports[ i ]->map, f ); +    trap_FS_Write( "time    = ", 10, f ); +    admin_writeconfig_string( g_admin_reports[ i ]->time, f ); +    trap_FS_Write( "players = ", 10, f ); +    admin_writeconfig_int( g_admin_reports[ i ]->players, f ); +    trap_FS_Write( "admins  = ", 10, f ); +    admin_writeconfig_string( g_admin_reports[ i ]->admins, f ); +    trap_FS_Write( "rep     = ", 10, f ); +    admin_writeconfig_string( g_admin_reports[ i ]->rep, f ); +    trap_FS_Write( "repIP   = ", 10, f );     +    admin_writeconfig_string( g_admin_reports[ i ]->repIP, f ); +    trap_FS_Write( "repGUID = ", 10, f );     +    admin_writeconfig_string( g_admin_reports[ i ]->repGUID, f ); +    trap_FS_Write( "level   = ", 10, f ); +    admin_writeconfig_int( g_admin_reports[ i ]->level, f ); +    trap_FS_Write( "note    = ", 10, f ); +    admin_writeconfig_string( g_admin_reports[ i ]->note, f ); +    trap_FS_Write( "expires = ", 10, f ); +    admin_writeconfig_int( g_admin_reports[ i ]->expires, f ); +    trap_FS_Write( "closed  = ", 10, f ); +    admin_writeconfig_int( g_admin_reports[ i ]->closed, f ); +    trap_FS_Write( "\n", 1, f ); +  } +    for( i = 0; i < MAX_ADMIN_ARCHIVES && g_admin_archives[ i ]; i++ ) +  {   +    if( ( g_admin_archives[ i ]->expires != 0  && ( g_admin_archives[ i ]->expires - t ) < 1 ) ) +    {  +        continue; +    } +       +    trap_FS_Write( "[archive]\n", 10, f ); +    trap_FS_Write( "name    = ", 10, f ); +    admin_writeconfig_string( g_admin_archives[ i ]->name, f ); +    trap_FS_Write( "guid    = ", 10, f ); +    admin_writeconfig_string( g_admin_archives[ i ]->guid, f ); +    trap_FS_Write( "ip      = ", 10, f ); +    admin_writeconfig_string( g_admin_archives[ i ]->ip, f ); +    trap_FS_Write( "reason  = ", 10, f ); +    admin_writeconfig_string( g_admin_archives[ i ]->reason, f ); +    trap_FS_Write( "map     = ", 10, f ); +    admin_writeconfig_string( g_admin_archives[ i ]->map, f ); +    trap_FS_Write( "time    = ", 10, f ); +    admin_writeconfig_string( g_admin_archives[ i ]->time, f ); +    trap_FS_Write( "players = ", 10, f ); +    admin_writeconfig_int( g_admin_archives[ i ]->players, f ); +    trap_FS_Write( "admins  = ", 10, f ); +    admin_writeconfig_string( g_admin_archives[ i ]->admins, f ); +    trap_FS_Write( "rep     = ", 10, f ); +    admin_writeconfig_string( g_admin_archives[ i ]->rep, f ); +    trap_FS_Write( "repIP   = ", 10, f );     +    admin_writeconfig_string( g_admin_archives[ i ]->repIP, f ); +    trap_FS_Write( "repGUID = ", 10, f );     +    admin_writeconfig_string( g_admin_archives[ i ]->repGUID, f ); +    trap_FS_Write( "level   = ", 10, f ); +    admin_writeconfig_int( g_admin_archives[ i ]->level, f ); +    trap_FS_Write( "note    = ", 10, f ); +    admin_writeconfig_string( g_admin_archives[ i ]->note, f ); +    trap_FS_Write( "expires = ", 10, f ); +    admin_writeconfig_int( g_admin_archives[ i ]->expires, f ); +    trap_FS_Write( "\n", 1, f ); +  } +  trap_FS_FCloseFile( f );  }  static void admin_readconfig_string( char **cnf, char *s, int size ) @@ -888,7 +1020,7 @@ qboolean G_admin_chat_readconfig( gentity_t *ent )    if( !g_chat.string[ 0 ] )    { -    ADMP( "chat_readconfig: g_chat is not set, not loading channel subscriptions " +    ADMP( "^3chat_readconfig: ^7g_chat is not set, not loading channel subscriptions "        "from a file\n" );      return qfalse;    } @@ -896,7 +1028,7 @@ qboolean G_admin_chat_readconfig( gentity_t *ent )    len = trap_FS_FOpenFile( g_chat.string, &f, FS_READ ) ;    if( len < 0 )    { -    ADMP( va( "chat_readconfig: could not open chat config file %s\n", +    ADMP( va( "^3chat_readconfig: ^7could not open chat config file %s\n",        g_chat.string ) );      return qfalse;    } @@ -956,7 +1088,7 @@ qboolean G_admin_chat_readconfig( gentity_t *ent )        }        else        { -        ADMP( va( "chat_readconfig: [chat] parse error near %s on line %d\n", +        ADMP( va( "^3chat_readconfig: ^7[chat] parse error near %s on line %d\n",            t, COM_GetCurrentParseLine() ) );        }      } @@ -965,7 +1097,7 @@ qboolean G_admin_chat_readconfig( gentity_t *ent )    }    G_Free( cnf2 ); -  ADMP( va( "chat_readconfig: loaded %d users with %d channels\n", uc, cc ) ); +  ADMP( va( "^3chat_readconfig: ^7loaded %d users with %d channels\n", uc, cc ) );    return qtrue;  } @@ -1842,42 +1974,46 @@ qboolean G_admin_readconfig( gentity_t *ent, int skiparg )    g_admin_level_t * l = NULL;    g_admin_admin_t *a = NULL;    g_admin_ban_t *b = NULL; +  g_admin_report_t *r = NULL; +  g_admin_archive_t *s = NULL;    g_admin_command_t *c = NULL; -  int lc = 0, ac = 0, bc = 0, cc = 0; +  int lc = 0, ac = 0, bc = 0, rc = 0, sc = 0, cc = 0;    fileHandle_t f;    int len;    char *cnf, *cnf2;    char *t; -  qboolean level_open, admin_open, ban_open, command_open; +  qboolean level_open, admin_open, ban_open, report_open, archive_open, command_open;    int i; - +      G_admin_cleanup();    if( !g_admin.string[ 0 ] )    { -    ADMP( "^3!readconfig: g_admin is not set, not loading configuration " -      "from a file\n" ); +    ADMP( "^3!readconfig: g_admin is not set, using the built-in set of admin levels, " +      "no ban entries, and no commands\n" );      admin_default_levels(); -    return qfalse; +    goto reportreadconfig;    } - +      len = trap_FS_FOpenFile( g_admin.string, &f, FS_READ ) ;    if( len < 0 )    {      ADMP( va( "^3!readconfig: ^7could not open admin config file %s\n",              g_admin.string ) );      admin_default_levels(); -    return qfalse; +    goto reportreadconfig;    } +      cnf = G_Alloc( len + 1 );    cnf2 = cnf;    trap_FS_Read( cnf, len, f );    *( cnf + len ) = '\0';    trap_FS_FCloseFile( f ); - -  t = COM_Parse( &cnf ); +   +  t = COM_Parse ( &cnf );    level_open = admin_open = ban_open = command_open = qfalse; -  while( *t ) +   +    while( *t )    {      if( !Q_stricmp( t, "[level]" ) ||           !Q_stricmp( t, "[admin]" ) || @@ -1892,9 +2028,8 @@ qboolean G_admin_readconfig( gentity_t *ent, int skiparg )        else if( ban_open )          g_admin_bans[ bc++ ] = b;        else if( command_open ) -        g_admin_commands[ cc++ ] = c; -      level_open = admin_open = -                     ban_open = command_open = qfalse; +         g_admin_commands[ cc++ ] = c; +      level_open = admin_open = ban_open = command_open = qfalse;      }      if( level_open ) @@ -2074,13 +2209,15 @@ qboolean G_admin_readconfig( gentity_t *ent, int skiparg )      g_admin_admins[ ac++ ] = a;    if( ban_open )      g_admin_bans[ bc++ ] = b; -  if( command_open ) -    g_admin_commands[ cc++ ] = c; -  G_Free( cnf2 ); -  ADMP( va( "^3!readconfig: ^7loaded %d levels, %d admins, %d bans, %d commands\n", -          lc, ac, bc, cc ) ); +   if( command_open ) +     g_admin_commands[ cc++ ] = c; +   G_Free( cnf2 ); +       if( lc == 0 ) +  {  +  ADMP( va( "^3!readconfig: ^7no admin levels found in %s, using the default set of admin levels\n", g_admin.string ) );      admin_default_levels(); +  }    else    {      char n[ MAX_NAME_LENGTH ] = {""}; @@ -2097,9 +2234,240 @@ qboolean G_admin_readconfig( gentity_t *ent, int skiparg )    for( i = 0; i < level.maxclients; i++ )      if( level.clients[ i ].pers.connected != CON_DISCONNECTED )        level.clients[ i ].pers.adminLevel = G_admin_level( &g_entities[ i ] ); +       +  reportreadconfig: +   +  if( !g_report.string[ 0 ] ) +  { +    ADMP( "^3!readconfig: g_report is not set, using no reports and no archives\n" ); +    ADMP( va( "^3!readconfig: ^7loaded %d levels, %d admins, %d bans, %d commands, %d reports, %d report archives\n", +        lc, ac, bc, cc, rc, sc ) ); +    return qtrue; +  } +   +  len = trap_FS_FOpenFile( g_report.string, &f, FS_READ ) ; +  if( len < 0 ) +  { +    ADMP( va( "^3!readconfig: ^7could not open report config file %s\n", +            g_report.string ) ); +    ADMP( va( "^3!readconfig: ^7loaded %d levels, %d admins, %d bans, %d commands, %d reports, %d report archives\n", +          lc, ac, bc, cc, rc, sc ) ); +    return qtrue; +  } +   +  cnf = G_Alloc( len + 1 ); +  cnf2 = cnf; +  trap_FS_Read( cnf, len, f ); +  *( cnf + len ) = '\0'; +  trap_FS_FCloseFile( f ); -  G_admin_chat_readconfig( ent ); +  t = COM_Parse ( &cnf ); +  report_open = archive_open = qfalse; +   +  while( *t ) +  { +    if( !Q_stricmp( t, "[report]" ) || +        !Q_stricmp( t, "[archive]" ) ) +    { + +      if( report_open ) +        g_admin_reports[ rc++ ] = r; +      else if( archive_open ) +        g_admin_archives[ sc++ ] = s; +    report_open = archive_open = qfalse; +    } + +    if( report_open ) +    { +      if( !Q_stricmp( t, "name" ) ) +      { +        admin_readconfig_string( &cnf, r->name, sizeof( r->name ) ); +      } +      else if( !Q_stricmp( t, "guid" ) ) +      { +        admin_readconfig_string( &cnf, r->guid, sizeof( r->guid ) ); +      } +      else if( !Q_stricmp( t, "ip" ) ) +      { +        admin_readconfig_string( &cnf, r->ip, sizeof( r->ip ) ); +      } +      else if( !Q_stricmp( t, "reason" ) ) +      { +        admin_readconfig_string( &cnf, r->reason, sizeof( r->reason ) ); +      } +      else if( !Q_stricmp( t, "map" ) ) +      { +        admin_readconfig_string( &cnf, r->map, sizeof( r->map ) ); +      } +      else if( !Q_stricmp( t, "time" ) ) +      { +        admin_readconfig_string( &cnf, r->time, sizeof( r->time ) ); +      } +      else if( !Q_stricmp( t, "players" ) ) +      { +        admin_readconfig_int( &cnf, &r->players ); +      } +      else if( !Q_stricmp( t, "admins" ) ) +      { +        admin_readconfig_string( &cnf, r->admins, sizeof( r->admins ) ); +      } +      else if( !Q_stricmp( t, "rep" ) ) +      { +        admin_readconfig_string( &cnf, r->rep, sizeof( r->rep ) ); +      } +      else if( !Q_stricmp( t, "repIP" ) ) +      { +        admin_readconfig_string( &cnf, r->repIP, sizeof( r->repIP ) ); +      } +      else if( !Q_stricmp( t, "repGUID" ) ) +      { +        admin_readconfig_string( &cnf, r->repGUID, sizeof( r->repGUID ) ); +      } +      else if( !Q_stricmp( t, "level" ) ) +      { +        admin_readconfig_int( &cnf, &r->level ); +      } +      else if( !Q_stricmp( t, "note" ) ) +      { +        admin_readconfig_string( &cnf, r->note, sizeof( r->note ) ); +      } +      else if( !Q_stricmp( t, "expires" ) ) +      { +        admin_readconfig_int( &cnf, &r->expires ); +      } +      else if( !Q_stricmp( t, "closed" ) ) +      { +        admin_readconfig_int( &cnf, &r->closed ); +      } +      else +      { +        ADMP( va( "^3!readconfig: ^7[report] parse error near %s on line %d\n", +                t, +                COM_GetCurrentParseLine() ) ); +      } +    } +    else if( archive_open ) +    { +      if( !Q_stricmp( t, "name" ) ) +      { +        admin_readconfig_string( &cnf, s->name, sizeof( s->name ) ); +      } +      else if( !Q_stricmp( t, "guid" ) ) +      { +        admin_readconfig_string( &cnf, s->guid, sizeof( s->guid ) ); +      } +      else if( !Q_stricmp( t, "ip" ) ) +      { +        admin_readconfig_string( &cnf, s->ip, sizeof( s->ip ) ); +      } +      else if( !Q_stricmp( t, "reason" ) ) +      { +        admin_readconfig_string( &cnf, s->reason, sizeof( s->reason ) ); +      } +      else if( !Q_stricmp( t, "map" ) ) +      { +        admin_readconfig_string( &cnf, s->map, sizeof( s->map ) ); +      } +      else if( !Q_stricmp( t, "time" ) ) +      { +        admin_readconfig_string( &cnf, s->time, sizeof( s->time ) ); +      } +      else if( !Q_stricmp( t, "players" ) ) +      { +        admin_readconfig_int( &cnf, &s->players ); +      } +      else if( !Q_stricmp( t, "admins" ) ) +      { +        admin_readconfig_string( &cnf, s->admins, sizeof( s->admins ) ); +      } +      else if( !Q_stricmp( t, "rep" ) ) +      { +        admin_readconfig_string( &cnf, s->rep, sizeof( s->rep ) ); +      } +      else if( !Q_stricmp( t, "repIP" ) ) +      { +        admin_readconfig_string( &cnf, s->repIP, sizeof( s->repIP ) ); +      } +      else if( !Q_stricmp( t, "repGUID" ) ) +      { +        admin_readconfig_string( &cnf, s->repGUID, sizeof( s->repGUID ) ); +      } +      else if( !Q_stricmp( t, "level" ) ) +      { +        admin_readconfig_int( &cnf, &s->level ); +      } +      else if( !Q_stricmp( t, "note" ) ) +      { +        admin_readconfig_string( &cnf, s->note, sizeof( s->note ) ); +      } +      else if( !Q_stricmp( t, "expires" ) ) +      { +        admin_readconfig_int( &cnf, &s->expires ); +      } +      else +      { +        ADMP( va( "^3!readconfig: ^7[archive] parse error near %s on line %d\n", +                t, +                COM_GetCurrentParseLine() ) ); +      } +    } +    if( !Q_stricmp( t, "[report]" ) ) +    { +      if( rc >= MAX_ADMIN_REPORTS ) +        return qfalse; +      r = G_Alloc( sizeof( g_admin_report_t ) ); +      *r->name = '\0'; +      *r->guid = '\0'; +      *r->ip = '\0'; +      *r->reason = '\0'; +      *r->map = '\0'; +      *r->time = '\0'; +      r->players = 0; +      *r->admins = '\0'; +      *r->rep = '\0'; +      *r->repIP = '\0'; +      *r->repGUID = '\0'; +      r->level = 0; +      *r->note = '\0'; +      r->expires = 0; +      r->closed = 0; +      report_open = qtrue; +    } +    else if( !Q_stricmp( t, "[archive]" ) ) +    { +      if( rc >= MAX_ADMIN_ARCHIVES ) +        return qfalse; +      s = G_Alloc( sizeof( g_admin_archive_t ) ); +      *s->name = '\0'; +      *s->guid = '\0'; +      *s->ip = '\0'; +      *s->reason = '\0'; +      *s->map = '\0'; +      *s->time = '\0'; +      s->players = 0; +      *s->admins = '\0'; +      *s->rep = '\0'; +      *s->repIP = '\0'; +      *s->repGUID = '\0'; +      s->level = 0; +      *s->note = '\0'; +      s->expires = 0; +      archive_open = qtrue; +    } +    t = COM_Parse( &cnf ); +  } +  if( report_open ) +    g_admin_reports[ rc++ ] = r; +  if( archive_open ) +  g_admin_archives[ sc++ ] = s; +   G_Free( cnf2 ); +    +  ADMP( va( "^3!readconfig: ^7loaded %d levels, %d admins, %d bans, %d reports, %d report archives, %d commands\n", +          lc, ac, bc, rc, sc, cc ) ); + +  G_admin_chat_readconfig( ent ); +      return qtrue;  } @@ -2113,6 +2481,20 @@ qboolean G_admin_time( gentity_t *ent, int skiparg )    return qtrue;  } +static int admin_guid_to_level(const char *guid) +{ +	int i; + +	if (!strcmp(guid, "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX")) +		return 0; + +	for (i = 0; i < MAX_ADMIN_ADMINS && g_admin_admins[i]; i++) +		if (!strcmp(guid, g_admin_admins[i]->guid)) +			return g_admin_admins[i]->level; + +	return 0; +} +  static int G_admin_find_slot( gentity_t *ent, char *namearg, const char *command )  {    char name[ MAX_NAME_LENGTH ]; @@ -5059,7 +5441,7 @@ qboolean G_admin_listplayers( gentity_t *ent, int skiparg )        {          // don't gather aka or level info if the admin is incognito -        if( ent && G_admin_permission( &g_entities[ i ], ADMF_INCOGNITO ) ) +        if( ent && G_admin_permission( &g_entities[ i ], ADMF_INCOGNITO ) && !G_admin_permission(ent, ADMF_SEESINCOGNITO) )          {            break;          } @@ -6689,6 +7071,9 @@ static AdminFlagListEntry_t adminFlagList[] =    { ADMF_TEAMCHANGEFREE,       "keeps credits on team switch" },    { ADMF_TEAMCHAT_CMD,         "can run commands from team chat" },    { ADMF_UNACCOUNTABLE,        "does not need to specify reason for kick/ban" }, +  { ADMF_NOREPORTLIMIT,        "does not have a report limit" }, +  { ADMF_FULLRLIST,            "removes self-restriction on report list" }, +  { ADMF_SEESINCOGNITO,        "sees registered name of players flagged with INCOGNITO" },    { ADMF_NO_CHAT,              "can not talk" },    { ADMF_NO_VOTE,              "can not call votes" }  }; @@ -8027,6 +8412,16 @@ void G_admin_cleanup()      G_Free( g_admin_commands[ i ] );      g_admin_commands[ i ] = NULL;    } +  for( i = 0; i < MAX_ADMIN_REPORTS && g_admin_reports[ i ]; i++ ) +  { +    G_Free( g_admin_reports[ i ] ); +    g_admin_reports[ i ] = NULL; +  } +  for( i = 0; i < MAX_ADMIN_ARCHIVES && g_admin_archives[ i ]; i++ ) +  { +    G_Free( g_admin_archives[ i ] ); +    g_admin_archives[ i ] = NULL; +  }    }  qboolean G_admin_L0(gentity_t *ent, int skiparg ){ @@ -8234,3 +8629,1186 @@ qboolean G_admin_invisible( gentity_t *ent, int skiparg )    return qtrue;  } +void G_admin_report_check( int clientNum ) +{ +  char *guid; +  char *ip; +  int i; +  gentity_t *ent; +  qboolean hasGuid; +   +  ent = &g_entities[ clientNum ]; +   +  guid = ent->client->pers.guid; +  ip = ent->client->pers.ip; +   +  hasGuid = !!Q_stricmp( guid, "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" ); +   +  for( i = 0; i < MAX_ADMIN_REPORTS && g_admin_reports[ i ]; i++ ) +  { +    if( g_admin_reports[ i ]->closed == 1 && +        ( ( hasGuid && !Q_stricmp( g_admin_reports[ i ]->repGUID, guid ) ) || +        ( !hasGuid && !Q_stricmp( g_admin_reports[ i ]->repIP, ip ) ) ) ) +    { +      ADMP( va("^5Your report for %s ^5was closed. Message from the admin:\n^7%s\n", +      g_admin_reports[ i ]->name, g_admin_reports[ i ]->reason ) ); +      g_admin_reports[ i ]->closed = 2; +     +        if( g_admin.string[ 0 ] ) +        { +          admin_writeconfig(); +        } +         +        if( hasGuid ) +        { +          break; +        } +    } +  } +  return; +} + +static qboolean admin_create_archive( gentity_t *ent, +  char *name, +  char *guid, +  char *ip, +  char *reason, +  char *map, +  char *time, +  int players, +  char *admins, +  char *rep, +  char *repIP, +  char *repGUID, +  int level, +  char *note, +  int seconds ) +  { +       +  g_admin_archive_t *s = NULL; +   +  qtime_t qt; +  int t; +  int i; + +  for( i = 0; i < MAX_ADMIN_ARCHIVES && g_admin_archives[ i ]; i++ ) +    ; +  if( i == MAX_ADMIN_ARCHIVES ) +  { +    ADMP( "^3!archive: ^7Too many archives\n" ); +    return qfalse; +  } +   +  t = trap_RealTime( &qt ); +  s = G_Alloc( sizeof( g_admin_archive_t ) ); + +  if( !s ) +    return qfalse; + +  Q_strncpyz( s->name, name, sizeof( s->name ) ); +  Q_strncpyz( s->guid, guid, sizeof( s->guid ) ); +  Q_strncpyz( s->ip, ip, sizeof( s->ip ) ); +  Q_strncpyz( s->reason, reason, sizeof( s->reason ) ); +  Q_strncpyz( s->map, map, sizeof( s->map ) ); +  Q_strncpyz( s->time, time, sizeof( s->time ) ); +  s->players = players; +  Q_strncpyz( s->admins, admins, sizeof( s->admins ) ); +  Q_strncpyz( s->rep, rep, sizeof( s->rep ) ); +  Q_strncpyz( s->repIP, repIP, sizeof(s->repIP) ); +  Q_strncpyz( s->repGUID, repGUID, sizeof(s->repGUID) ); +  s->level = G_admin_level( ent ); +  Q_strncpyz( s->note, note, sizeof(s->note) ); +  if( !seconds ) { +    s->expires = 0; +  } else { +    s->expires = t + seconds; +  } + +  g_admin_archives[ i ] = s; +  return qtrue; +} + +static qboolean admin_create_report( gentity_t *ent, +  char *name, +  char *guid, +  char *ip, +  char *reason, +  char *map, +  char *time, +  int players, +  char *admins, +  char *rep, +  char *repIP, +  char *repGUID, +  int level, +  char *note, +  int seconds, +  int closed ) +  { +       +  g_admin_report_t *r = NULL; +   +   +  qtime_t qt; +  int t; +  int i; +   +  for( i = 0; i < MAX_ADMIN_REPORTS && g_admin_reports[ i ]; i++ ) +    ; +  if( i == MAX_ADMIN_REPORTS ) +  { +    ADMP( "^3!report: ^7Too many reports\n" ); +    return qfalse; +  } + +  t = trap_RealTime( &qt ); +  r = G_Alloc( sizeof( g_admin_report_t ) ); + +  if( !r ) +    return qfalse; + +  Q_strncpyz( r->name, name, sizeof( r->name ) ); +  Q_strncpyz( r->guid, guid, sizeof( r->guid ) ); +  Q_strncpyz( r->ip, ip, sizeof( r->ip ) ); +  Q_strncpyz( r->reason, reason, sizeof( r->reason ) ); +  Q_strncpyz( r->map, map, sizeof( r->map ) ); +  Q_strncpyz( r->time, time, sizeof( r->time ) ); +  r->players = players; +  Q_strncpyz( r->admins, admins, sizeof( r->admins ) ); +  Q_strncpyz( r->rep, rep, sizeof( r->rep ) ); +  Q_strncpyz( r->repIP, repIP, sizeof(r->repIP) ); +  Q_strncpyz( r->repGUID, repGUID, sizeof(r->repGUID) ); +  r->level = G_admin_level( ent ); +  Q_strncpyz( r->note, note, sizeof(r->note) ); +  if( !seconds ) { +    r->expires = 0; +  } else { +    r->expires = t + seconds; +  } +  r->closed = closed; + +  g_admin_reports[ i ] = r; +  return qtrue; +} + +qboolean G_admin_report( gentity_t *ent, int skiparg ) +{ +  char *reason; +  char search[ MAX_NAME_LENGTH ]; +  char n2[ MAX_NAME_LENGTH ]; +  char s2[ MAX_NAME_LENGTH ]; +  char admins[256] = {0}; +  char time[ 48 ]; +  char map[ 32 ]; +  int i, j, min, tens, sec;  +  int logmatch = -1, logmatches = 0, repcount = 0; +  qboolean exactmatch = qfalse; +  qtime_t qt; +  gentity_t *vic; +   +  if( G_SayArgc() < 3 + skiparg ) +  { +    ADMP( "^3!report: ^7usage: !report [name|slot] [reason/additional info]\n" ); +    return qfalse; +  } + +  trap_RealTime( &qt ); +   +    sec = ( level.time - level.startTime ) / 1000; + +    min = sec / 60; +    sec -= min * 60; +    tens = sec / 10; +    sec -= tens * 10; +   +  if( !G_admin_permission( ent, ADMF_NOREPORTLIMIT ) ) +  { +    for( i = 0; i < MAX_ADMIN_REPORTS && g_admin_reports[ i ]; i++ ) +    { +      if( !Q_stricmp( ent->client->pers.ip, g_admin_reports[ i ]->repIP ) || +          !Q_stricmp( ent->client->pers.guid, g_admin_reports[ i ]->repGUID ) ) +      { +        repcount++; +      } + +      if( ( G_admin_level( ent ) == 0 && repcount >= g_maxUnregReports.integer ) +          || repcount >= g_maxReports.integer ) +      { +        ADMP( "^5Your report limit was reached. You can view your reports using !rlist^7\n" ); +         +        if( repcount < g_maxReports.integer )  +        { +          ADMP( va( "^5^5Register to gain ^7%i ^5extra report slots.\n", (g_maxReports.integer - g_maxUnregReports.integer) ) ); +        } +         +        return qfalse; +      } +    } +  } +   +  G_SayArgv( 1 + skiparg, search, sizeof( search ) ); +  G_SanitiseString( search, s2, sizeof( s2 ) ); +  reason = G_SayConcatArgs( 2 + skiparg ); + +  for( i = 0; i < MAX_ADMIN_NAMELOGS && g_admin_namelog[ i ]; i++ ) +  { + +    if( g_admin_namelog[ i ]->slot == -1 ) +      continue; + +    if( !Q_stricmp( va( "%d", g_admin_namelog[ i ]->slot ), s2 ) ) +    { +      logmatches = 1; +      logmatch = i; +      exactmatch = qtrue; +      break; +    } +  }  + +  for( i = 0; +       !exactmatch && i < MAX_ADMIN_NAMELOGS && g_admin_namelog[ i ]; +       i++ ) +  { +    for( j = 0; j < MAX_ADMIN_NAMELOG_NAMES && +         g_admin_namelog[ i ]->name[ j ][ 0 ]; j++ ) +    { +      G_SanitiseString(g_admin_namelog[ i ]->name[ j ], n2, sizeof( n2 ) ); +     +      if( strstr( n2, s2 ) ) +      { +      if( logmatch != i ) +          logmatches++; +          logmatch = i;  +      } +    } +  } +   +  if( !logmatches )  +  { +    ADMP( "^3!report: ^7no player found by that name or slot number\n" ); +    return qfalse; +  }  +  else if( logmatches > 1 ) +  { +    ADMBP_begin(); +    ADMBP( "^3!report: ^7multiple recent clients match name, use slot#:\n" ); +     +    for( i = 0; i < MAX_ADMIN_NAMELOGS && g_admin_namelog[ i ]; i++ ) +    { +      for( j = 0; j < MAX_ADMIN_NAMELOG_NAMES && +           g_admin_namelog[ i ]->name[ j ][ 0 ]; j++ ) +      { +        G_SanitiseString(g_admin_namelog[ i ]->name[ j ], n2, sizeof( n2 ) ); +         +        if( strstr( n2, s2 ) ) +        { +          if( g_admin_namelog[ i ]->slot > -1 ) +            ADMBP( "^3" ); +            ADMBP( va( "%-2s ^7- '%s^7'\n", +              (g_admin_namelog[ i ]->slot > -1) ? +            va( "%d", g_admin_namelog[ i ]->slot ) : "-", +               g_admin_namelog[ i ]->name[ j ] ) ); +        } +      } +    } +    ADMBP_end(); +    return qfalse; +  } +     +  for( i = 0; i < level.maxclients; i++ ) +  {         +    vic = &g_entities[ i ]; + +    if( G_admin_level( vic ) >= 3 ) +    {     +      Q_strcat( admins, sizeof(admins), va( "%s^7 ", G_admin_get_adminname( vic ) ) ); +    } +  } +     +    trap_Cvar_VariableStringBuffer( "mapname", map, sizeof( map ) ); +    Q_strncpyz( time, va( "^3%02i/%02i/%02i^7 - ^3%02i:%02i^7 - Game time: ^3%i:%i%i", qt.tm_year+1900, qt.tm_mon+1, qt.tm_mday, qt.tm_hour, qt.tm_min, min, tens, sec ), sizeof(time) ); +	 +    admin_create_report( ent, +      g_admin_namelog[ logmatch ]->name[0], +      g_admin_namelog[ logmatch ]->guid, +      g_admin_namelog[ logmatch ]->ip, +      reason, map, time, level.numConnectedClients, admins, +      ( ent ) ? ent->client->pers.netname : "console", ent->client->pers.ip, ent->client->pers.guid, G_admin_level( ent ), +      "No notes - Edit this using !rnote", G_admin_parse_time("1w"), 0 );  + +  if( !g_admin.string[ 0 ] ) +    G_LogPrintf( "^3!report: ^7WARNING g_report not set, not saving report to a file\n" ); +  else +    admin_writeconfig(); +     +      G_AdminsPrintf( va( "New pending report from %s\n", ( ent ) ? G_admin_adminPrintName( ent ) : "console" ) ); + +  ADMP( va( "^5You reported: ^7%s\n%s%s", g_admin_namelog[ logmatch ]->name[ 0 ], g_reportWelcomeComment.string, +      ( g_reportWelcomeComment.string[ 0 ] ? "\n" : "" ) ) ); +   +  return qtrue; +} + +qboolean G_admin_rlist( gentity_t *ent, int skiparg ) +{ +  char filter[ MAX_NAME_LENGTH ] = {""}; +  char n1[ MAX_NAME_LENGTH * 2 ] = {""}; +  char n2[ MAX_NAME_LENGTH * 2 ] = {""}; +  char name_fmt[ 32 ] = { "%s" }; +  char reporter_fmt[ 32 ] = { "%s" }; +  char name_match[ MAX_NAME_LENGTH ] = {""}; +  char duration[ 32 ]; +  char *ip_match = NULL; +  int i, t; +  int show_count = 0; +  int max_name = 1, max_reporter = 1; +  int ip_match_len = 0; +  int found = 0; +  int secs; +  int start = 0; +  qboolean numeric = qtrue; +  qboolean subnetfilter = qfalse; +  qtime_t qt; +  g_admin_report_t *report; + +    t = trap_RealTime( &qt ); +   +  if( !G_admin_permission( ent, ADMF_FULLRLIST ) ) +  { +    ADMBP_begin(); +    for( i = 0; i < MAX_ADMIN_REPORTS && g_admin_reports[ i ]; i++ ) +    { +        report = g_admin_reports[ i ]; +         +      if( !Q_stricmp( report->repGUID, ent->client->pers.guid ) && +          report->closed == 0 ) +      { +        G_DecolorString( g_admin_reports[ i ]->name, n1 ); +        Com_sprintf( name_fmt, sizeof( name_fmt ), "%%%is", +          ( max_name + (int)( strlen( g_admin_reports[ i ]->name ) - strlen( n1 ) ) ) ); +        Com_sprintf( n1, sizeof( n1 ), name_fmt, g_admin_reports[ i ]->name );  +        +        ADMBP( va( "%4i %s^7         Made: %s^7 on ^3%s^7 with ^3%i^7 players online\n     \\__ ^5%s^7\n", +           ( 1 + found ), +           n1, +           report->time, +           report->map, +           report->players, +           report->reason ) ); +             +           found++; +      } +    } +     +    ADMBP_end(); +     +    if( found == 0 ) +    { +        ADMP( "^3!rlist: ^7You don't have any open reports pending.\n" ); +    } +    return qtrue; +  } +   +  for( i = 0; i < MAX_ADMIN_REPORTS && g_admin_reports[ i ]; i++ ) +  { +    if( g_admin_reports[ i ]->expires != 0  && +        g_admin_reports[ i ]->expires - t < 1 && +        g_admin_reports[ i ]->closed != 0 ) +    { +      continue; +    } +    found++; +  } + +   +  if( G_SayArgc() >= 2 + skiparg ) +  { +    G_SayArgv( 1 + skiparg, filter, sizeof( filter ) ); +    if( G_SayArgc() >= 3 + skiparg ) +    { +      start = atoi( filter ); +      G_SayArgv( 2 + skiparg, filter, sizeof( filter ) ); +    } +    for( i = 0; i < sizeof( filter ) && filter[ i ] ; i++ ) +    { +      if( ( filter[ i ] < '0' || filter[ i ] > '9' ) && +            filter[ i ] != '.' && filter[ i ] != '-' ) +      { +        numeric = qfalse; +        break; +      } +    } + +    if (!numeric) +    { +      if( filter[ 0 ] != '-' ) +      { +        G_SanitiseString( filter, name_match, sizeof( name_match) ); + +      } +      else +      { +        if( !Q_strncmp( filter, "-sub", 4 ) ) +        { +          subnetfilter = qtrue; +        } else { +          ADMP( va( "^3!rlist: ^7invalid argument %s\n", filter ) ); +          return qfalse; +        } +      } +    } +    else if( strchr( filter, '.' ) != NULL ) +    { +      ip_match = filter; +      ip_match_len = strlen(ip_match); +    } +    else +    { +      start = atoi( filter ); +      filter[0] = '\0'; +    } +     +    if( start > 0 ) +      start -= 1; +    else if( start < 0 ) +      start = found + start; +  } +   +  if( start >= MAX_ADMIN_REPORTS || start < 0 ) +    start = 0; + +  for( i = start; i < MAX_ADMIN_REPORTS && g_admin_reports[ i ] && +       show_count < MAX_ADMIN_SHOWREPORTS; i++ ) +  { +    qboolean match = qfalse; +    report = g_admin_reports[ i ]; + +    if (!numeric) +      { +        if( !subnetfilter ) +        { +          G_SanitiseString( report->name, n1, sizeof( n1 ) ); +          if (strstr( n1, name_match) ) +            match = qtrue; +        } else { +          int mask = -1; +          int dummy; +          int scanflen = 0; +          scanflen = sscanf( report->ip, "%d.%d.%d.%d/%d", &dummy, &dummy, &dummy, &dummy, &mask ); +          if( scanflen == 5 && mask < 32 ) +          { +            match = qtrue; +          } +        } +      } + +    if ( ( match ) || !ip_match || +           Q_strncmp( ip_match, report->ip, ip_match_len) == 0 ) +    { +      G_DecolorString( report->name, n1 ); +      G_DecolorString( report->rep, n2 ); +       +      if( strlen( n1 ) > max_name ) +      { +        max_name = strlen( n1 ); +      } +      if( strlen( n2 ) > max_reporter ) +        max_reporter = strlen( n2 ); +  +      show_count++; +    } +  } + +  if( start >= found ) +  { +    ADMP( va( "^3!rlist: ^7there are %d active reports\n", found ) ); +    return qfalse; +  } +   +    ADMBP_begin(); +    show_count = 0; +     +  for( i = start; i < MAX_ADMIN_REPORTS && g_admin_reports[ i ] && +       show_count < MAX_ADMIN_SHOWREPORTS; i++ ) +  { +    report = g_admin_reports[ i ]; +      +    if (!numeric) +    { +      if( !subnetfilter ) +      { +        G_SanitiseString( report->name, n1, sizeof( n1 ) ); +        if ( strstr ( n1, name_match ) == NULL ) +          continue; +      } else { +        int mask = -1; +        int dummy; +        int scanflen = 0; +        scanflen = sscanf( report->ip, "%d.%d.%d.%d/%d", &dummy, &dummy, &dummy, &dummy, &mask ); +         +        if( scanflen != 5 || mask >= 32 ) +        { +          continue; +        } +      } +    } +    else if( ip_match != NULL +      && Q_strncmp( ip_match, report->ip, ip_match_len ) != 0) +      continue; +     +    if( ( report->expires == 0 || report->expires - t >= 1 ) && report->closed == 0 ) +    { +      G_DecolorString( report->name, n1 ); +      Com_sprintf( name_fmt, sizeof( name_fmt ), "%%%is", +        ( max_name + (int)( strlen( report->name ) - strlen( n1 ) ) ) ); +      Com_sprintf( n1, sizeof( n1 ), name_fmt, report->name );  + +      G_DecolorString( report->rep, n2 ); +      Com_sprintf( reporter_fmt, sizeof( reporter_fmt ), "%%%is", +        ( max_reporter + (int)( strlen( report->rep ) - strlen( n2 ) ) ) ); +      Com_sprintf( n2, sizeof( n2 ), reporter_fmt, report->rep ); +         +      secs = ( report->expires - t ); +      G_admin_duration( secs, duration, sizeof( duration ) ); +       +      ADMBP( va( "%4i %s^7 %-15s       Expires: %s\n     |  Reported by: %-15s^7 Level:%2i\n     |  ^5%s^7\n     |  Made: %s^7 on ^3%s^7 with ^3%i^7 players online\n     |  Admins online: %s^7\n     \\__ ^5Note: %s^7\n", +        ( i + 1 ), +        n1, +        report->ip, +        duration, +        n2, +        report->level, +        report->reason, +        report->time, +        report->map, +        report->players, +        report->admins, +        report->note ) ); +		 +      show_count++; +    } +  } + +  if (!numeric || ip_match) +  { +    char matchmethod[50]; +     +    if( numeric )  +      Com_sprintf( matchmethod, sizeof(matchmethod), "IP" ); +    else if( !subnetfilter ) +      Com_sprintf( matchmethod, sizeof(matchmethod), "name" ); +    else +      Com_sprintf( matchmethod, sizeof(matchmethod), "ip range size" ); + +    ADMBP( va( "^3!rlist:^7 found %d matching reports by %s.", +             show_count, +             matchmethod ) ); +  } else { +    ADMBP( va( "^3!rlist:^7 showing reports %d - %d of %d.", +             ( found ) ? ( start + 1 ) : 0, +             ( ( start + MAX_ADMIN_SHOWREPORTS ) > found ) ? +             found : ( start + MAX_ADMIN_SHOWREPORTS ), +             found ) ); +  } + +  if( ( start + MAX_ADMIN_SHOWREPORTS ) < found ) +  { +    ADMBP( va( "run !rlist %d %s to see more", +             ( start + MAX_ADMIN_SHOWREPORTS + 1 ), +             (filter[0]) ? filter : "" ) ); +  } + +  ADMBP( "^3rlist:^7 run ^3!rshow^7 <entry> to see all details about a report" ); +   +  ADMBP( "\n" ); +  ADMBP_end(); +  return qtrue; +} + +qboolean G_admin_rban( gentity_t *ent, int skiparg ) +{ +  int seconds; +  char *reason; +  int minargc; +  char duration[ 32 ]; +  char notice[51];  +  char arg1[ 5 ]; +  char arg2[ 7 ]; +  int i, ID; +  g_admin_report_t *report; +  gclient_t *client; +   +    trap_Cvar_VariableStringBuffer( "g_banNotice", notice, sizeof( notice ) ); +   +  if( G_admin_permission( ent, ADMF_CAN_PERM_BAN ) && +       G_admin_permission( ent, ADMF_UNACCOUNTABLE ) ) +  { +    minargc = 2 + skiparg; +  } +  else if( G_admin_permission( ent, ADMF_CAN_PERM_BAN ) || +           G_admin_permission( ent, ADMF_UNACCOUNTABLE ) || +           g_adminMaxBan.integer ) +  { +    minargc = 3 + skiparg; +  } +  else +  { +    minargc = 4 + skiparg; +  } +  if( G_SayArgc() < minargc ) +  { +    ADMP( "^3!rban: ^7usage: !rban [report#] [time] [reason]\n" ); +    return qfalse; +  } +   +    G_SayArgv( 1 + skiparg, arg1, sizeof( arg1 ) ); +    ID = atoi( arg1 ); +   +  if( ID < 1 || +      ID > MAX_ADMIN_REPORTS || +      !g_admin_reports[ ID - 1 ] || +      g_admin_reports[ ID - 1 ]->closed == 2 ) +  { +    ADMP( "^3!rban: ^7invalid report#\n" ); +    return qfalse; +  } +   +    report = g_admin_reports[ ID - 1 ]; +      +    if( admin_guid_to_level( ent->client->pers.guid ) < +        admin_guid_to_level( g_admin_reports[ ID ]->guid ) ) +    { +      ADMP( "Your target has a higher admin level than you." ); +      return qfalse; +    } +	 +    G_SayArgv( 2 + skiparg, arg2, sizeof( arg2 ) ); +    seconds = G_admin_parse_time( arg2 ); +     +  if( seconds <= 0 ) +  { +    if( g_adminMaxBan.integer && !G_admin_permission( ent, ADMF_CAN_PERM_BAN ) ) +    { +      ADMP( va( "^3!rban: ^7using your admin level's maximum ban length of %s\n", +        g_adminMaxBan.string ) ); +      seconds = G_admin_parse_time( g_adminMaxBan.string ); +    } +    else if( G_admin_permission( ent, ADMF_CAN_PERM_BAN ) ) +    { +      seconds = 0; +    } +    else +    { +      ADMP( "^3!rban: ^7ban time must be positive\n" ); +      return qfalse; +    } +    reason = G_SayConcatArgs( 2 + skiparg ); +  } +  else +  { +    reason = G_SayConcatArgs( 3 + skiparg ); + +    if( g_adminMaxBan.integer && +        seconds > G_admin_parse_time( g_adminMaxBan.string ) && +        !G_admin_permission( ent, ADMF_CAN_PERM_BAN ) ) +    { +      seconds = G_admin_parse_time( g_adminMaxBan.string ); +      ADMP( va( "^3!rban: ^7ban length limited to %s for your admin level\n", +        g_adminMaxBan.string ) ); +    } +  } + +  G_admin_duration( ( seconds ) ? seconds : -1, +    duration, sizeof( duration ) ); +     +  admin_create_ban( ent, +    report->name, +    report->guid, +    report->ip, +    seconds, reason );  + +  if( !g_admin.string[ 0 ] ) +    ADMP( "^3!rban: ^7WARNING g_admin not set, not saving ban to a file\n" ); +  else +    admin_writeconfig(); + +    AP( va( "print \"^3!rban:^7 %s^7 has been banned by %s^7 " +      "duration: %s, reason: %s\n\"", +      report->name, +      ( ent ) ? G_admin_adminPrintName( ent ) : "console", +      duration, +      ( *reason ) ? reason : "banned by admin" ) ); +      +  for( i = 0; i < level.maxclients; i++ ) +  { +    client = &level.clients[ i ]; +     +    if( client->pers.connected == CON_DISCONNECTED ) +    { +      continue; +    } + +    if( !Q_stricmp( client->pers.ip, report->ip ) || +        ( Q_stricmp( report->guid, "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" ) && +          !Q_stricmp ( client->pers.guid, report->guid ) ) ) +   +  trap_DropClient( i, +    va( "banned by %s^7, duration: %s, reason: %s", +      ( ent ) ? G_admin_adminPrintName( ent ) : "console", +      duration, +      ( *reason ) ? reason : "banned by admin" ) ); +  } +           +  return qtrue; +} + +qboolean G_admin_rclose( gentity_t *ent, int skiparg ) +{ +  char *reason; +  char arg1[ 5 ]; +  char arg2[ 2 ]; +  int i, ID; +  gclient_t *client; +  g_admin_report_t *report; +   +  if( G_SayArgc() < 3 + skiparg ) +  { +    ADMP( "^3!rclose: ^7usage: !rclose [report#] (!) [message] - ! saves it as archive\n" ); +    return qfalse; +  } +   +  G_SayArgv( 1 + skiparg, arg1, sizeof( arg1 ) ); +  ID = atoi( arg1 ); +   +  if( ID < 1 || ID > MAX_ADMIN_REPORTS || !g_admin_reports[ ID - 1 ] || g_admin_reports[ ID - 1 ]->closed >= 1 ) +  { +    ADMP( "^3!rclose: ^7invalid report#\n" ); +    return qfalse; +  } +   +  report = g_admin_reports[ ID - 1 ]; +   +  G_SayArgv( 2 + skiparg, arg2, sizeof( arg2 ) ); +  reason = G_SayConcatArgs( 3 + skiparg ); +   +  if( !strcmp( arg2, "!" ) ) +  { +    admin_create_archive( ent, +      report->name, +      report->guid, +      report->ip, +      report->reason, +      report->map, +      report->time, +      report->players, +      report->admins, +      report->rep, +      report->repIP, +      report->repGUID, +      report->level, +      report->note, +      G_admin_parse_time("12w") ); +       +    G_AdminsPrintf( va( "%s ^7closed and archived report #%i\n", +      ( ent ) ? G_admin_adminPrintName( ent ) : "console", ID ) ); +  } else { +    reason = G_SayConcatArgs( 2 + skiparg ); +    G_AdminsPrintf( va( "%s ^7closed report #%i\n", +      ( ent ) ? G_admin_adminPrintName( ent ) : "console", +      ID ) ); +  } +   +  report->closed = 1;     +  Q_strncpyz( report->reason, reason, sizeof( report->reason ) ); + +  for( i = 0; i < level.maxclients ; i++ ) +  { +    client = &level.clients[ i ]; +   +    if( client->pers.connected == CON_DISCONNECTED ) +    { +      continue; +    } +     +    if( !Q_stricmp( report->repGUID, client->pers.guid ) || +        !strcmp( report->repIP, client->pers.ip ) ) +    { +      trap_SendServerCommand( i, va( "print \"^5Your report for %s ^5was closed. Message from the admin:\n^7%s\n\"", +        report->name, report->reason ) ); +      report->closed = 2;  +      break; +    } +  } + +  if( !g_admin.string[ 0 ] ) +    ADMP( "^3!rclose: ^7WARNING g_admin not set, not saving report to a file\n" ); +  else +    admin_writeconfig(); +     +  return qtrue; +} + +qboolean G_admin_rarclist( gentity_t *ent, int skiparg ) +{ +  char filter[ MAX_NAME_LENGTH ] = {""}; +  char n1[ MAX_NAME_LENGTH * 2 ] = {""}; +  char n2[ MAX_NAME_LENGTH * 2 ] = {""}; +  char name_fmt[ 32 ] = { "%s" }; +  char reporter_fmt[ 32 ] = { "%s" }; +  char name_match[ MAX_NAME_LENGTH ] = {""}; +  char duration[ 32 ]; +  char *ip_match = NULL; +  int show_count = 0; +  int max_name = 1, max_reporter = 1; +  int ip_match_len = 0; +  int secs; +  int found = 0; +  int start = 0; +  int i, t; +  qboolean numeric = qtrue; +  qboolean subnetfilter = qfalse; +  g_admin_archive_t *archive; +  qtime_t qt; + +    t = trap_RealTime( &qt ); +   +  for( i = 0; i < MAX_ADMIN_ARCHIVES && g_admin_archives[ i ]; i++ ) +  { +    archive = g_admin_archives[ i ]; +     +    if( archive->expires != 0  && +        archive->expires - t < 1 ) +    { +      continue; +    } +    found++; +  } + +   +  if( G_SayArgc() >= 2 + skiparg ) +  { +    G_SayArgv( 1 + skiparg, filter, sizeof( filter ) ); +    if( G_SayArgc() >= 3 + skiparg ) +    { +      start = atoi( filter ); +      G_SayArgv( 2 + skiparg, filter, sizeof( filter ) ); +    } +    for( i = 0; i < sizeof( filter ) && filter[ i ] ; i++ ) +    { +      if( ( filter[ i ] < '0' || filter[ i ] > '9' ) && +            filter[ i ] != '.' && filter[ i ] != '-' ) +      { +        numeric = qfalse; +        break; +      } +    } + +    if (!numeric) +    { +      if( filter[ 0 ] != '-' ) +      { +        G_SanitiseString( filter, name_match, sizeof( name_match) ); + +      } else { +        if( !Q_strncmp( filter, "-sub", 4 ) ) +        { +          subnetfilter = qtrue; +        } else { +          ADMP( va( "^3!rarclist: ^7invalid argument %s\n", filter ) ); +          return qfalse; +        } +      } +    } +    else if( strchr( filter, '.' ) != NULL ) +    { +      ip_match = filter; +      ip_match_len = strlen(ip_match); +    } else { +      start = atoi( filter ); +      filter[0] = '\0'; +    } +     +    if( start > 0 ) +      start -= 1; +    else if( start < 0 ) +      start = found + start; +  } +   +  if( start >= MAX_ADMIN_ARCHIVES || start < 0 ) +    start = 0; + +  for( i = start; i < MAX_ADMIN_ARCHIVES && g_admin_archives[ i ]  +    && show_count < MAX_ADMIN_SHOWREPORTS; i++ ) +  { +    qboolean match = qfalse; +    archive = g_admin_archives[ i ]; + +    if (!numeric) +      { +        if( !subnetfilter ) +        { +          G_SanitiseString( archive->name, n1, sizeof( n1 ) ); +          if (strstr( n1, name_match) ) +            match = qtrue; +        } +        else +        { +          int mask = -1; +          int dummy; +          int scanflen = 0; +          scanflen = sscanf( archive->ip, "%d.%d.%d.%d/%d", &dummy, &dummy, &dummy, &dummy, &mask ); +          if( scanflen == 5 && mask < 32 ) +          { +            match = qtrue; +          } +        } +      } + +    if ( ( match ) || !ip_match || +         Q_strncmp( ip_match, archive->ip, ip_match_len) == 0 ) +    { +      G_DecolorString( archive->name, n1 ); +      G_DecolorString( archive->rep, n2 ); +       +      if( strlen( n1 ) > max_name ) +      { +        max_name = strlen( n1 ); +      } +      if( strlen( n2 ) > max_reporter ) +        max_reporter = strlen( n2 ); +  +      show_count++; +    } +  } + +  if( start >= found ) +  { +    ADMP( va( "^3!rarclist: ^7there are %d archived reports\n", found ) ); +    return qfalse; +  } +   +  ADMBP_begin(); +  show_count = 0; +   +  for( i = start; i < MAX_ADMIN_ARCHIVES && g_admin_archives[ i ] && +       show_count < MAX_ADMIN_SHOWREPORTS; i++ ) +  { +    archive = g_admin_archives[ i ]; +    if (!numeric) +    { +      if( !subnetfilter ) +      { +        G_SanitiseString( archive->name, n1, sizeof( n1 ) ); +        if ( strstr ( n1, name_match ) == NULL ) +          continue; +      } +      else +      { +        int mask = -1; +        int dummy; +        int scanflen = 0; +        scanflen = sscanf( archive->ip, "%d.%d.%d.%d/%d", &dummy, &dummy, &dummy, &dummy, &mask ); +        if( scanflen != 5 || mask >= 32 ) +        { +          continue; +        } +      } +    } +    else if( ip_match != NULL && +             Q_strncmp( ip_match, archive->ip, ip_match_len ) != 0) +      continue; +     +    if( archive->expires == 0 || archive->expires - t >= 1 ) +    { +      G_DecolorString( archive->name, n1 ); +      Com_sprintf( name_fmt, sizeof( name_fmt ), "%%%is", +        ( max_name + (int)( strlen( archive->name ) - strlen( n1 ) ) ) ); +      Com_sprintf( n1, sizeof( n1 ), name_fmt, archive->name );  + +      G_DecolorString( archive->rep, n2 ); +      Com_sprintf( reporter_fmt, sizeof( reporter_fmt ), "%%%is", +        ( max_reporter + (int)( strlen( archive->rep ) - strlen( n2 ) ) ) ); +      Com_sprintf( n2, sizeof( n2 ), reporter_fmt, archive->rep ); +         +      secs = ( archive->expires - t ); +      G_admin_duration( secs, duration, sizeof( duration ) ); +       +    ADMBP( va( "%4i %s^7 %-15s       Archive expires in: %s\n     |  Reported by: %-15s^7 Level:%2i\n     |  ^5%s^7\n     |  Made: %s^7 on ^3%s^7 with ^3%i^7 players online\n     |  Admins online: %s\n     \\__ Note: ^5%s^7\n", +             ( i + 1 ), +             n1, +             archive->ip, +             duration, +             n2, +             archive->level, +             archive->reason, +             archive->time, +             archive->map, +             archive->players, +             archive->admins, +             archive->note ) ); +    } +    show_count++; +  } + +  if (!numeric || ip_match) +  { +    char matchmethod[50]; +    if( numeric )  +      Com_sprintf( matchmethod, sizeof(matchmethod), "IP" ); +    else if( !subnetfilter ) +      Com_sprintf( matchmethod, sizeof(matchmethod), "name" ); +    else +      Com_sprintf( matchmethod, sizeof(matchmethod), "ip range size" ); + + +    ADMBP( va( "^3!rarclist:^7 found %d matching archived reports by %s.  ", +             show_count, +             matchmethod ) ); +  } +  else +  { +    ADMBP( va( "^3!rarclist:^7 showing archived reports %d - %d of %d.  ", +             ( found ) ? ( start + 1 ) : 0, +             ( ( start + MAX_ADMIN_SHOWREPORTS ) > found ) ? +             found : ( start + MAX_ADMIN_SHOWREPORTS ), +             found ) ); +  } + +  if( ( start + MAX_ADMIN_SHOWREPORTS ) < found ) +  { +    ADMBP( va( "run !rarclist %d %s to see more", +             ( start + MAX_ADMIN_SHOWREPORTS + 1 ), +             (filter[0]) ? filter : "" ) ); +  } + +  ADMBP( "^3rlist:^7 run ^3!rshow^7 ^5!^7 <entry> to see all details about an archive" ); +   +  ADMBP( "\n" ); +  ADMBP_end(); +  return qtrue; +} + +qboolean G_admin_rpurge( gentity_t *ent, int skiparg ) +{ +  char arg2[ 5 ]; +  char tmp[ 2 ]; +  int ID, t; + +  t = trap_RealTime( NULL ); +   +  if( G_SayArgc() < 2 + skiparg ) +  { +    ADMP( "^3!rpurge: ^7usage: !rpurge [reportid#] (!) - if '!' is specified, acts on archive# instead\n" ); +    return qfalse; +  } +   +  G_SayArgv( 1 + skiparg, arg2, sizeof( arg2 ) ); +  ID = atoi( arg2 ); + +  if( G_SayArgc() >= 3 + skiparg ) +  { +    G_SayArgv( 2 + skiparg, tmp, sizeof( tmp ) ); +   +    if( !strcmp( tmp, "!") ) +    { +      if( ID < 1 || +          ID > MAX_ADMIN_ARCHIVES || +          !g_admin_archives[ ID - 1 ] || +        ( g_admin_archives[ ID - 1 ]->expires != 0 && g_admin_archives[ ID - 1 ]->expires - t < 1 ) ) +      { +        ADMP( "^3!rpurge: ^7invalid report archive#\n" ); +        return qfalse; +      } +       +      G_AdminsPrintf( va( "%s ^7purged archived report #%i\n", +                        ( ent ) ? G_admin_adminPrintName( ent ) : "console", ID ) ); +      g_admin_archives[ ID - 1 ]->expires = t; +       +      if( g_report.string[ 0 ] ) +      admin_writeconfig(); +       +      return qtrue; +    } else { +      ADMP( "^1WROOOOOOOOONG!^7: ^3!rpurge: ^7usage: !rpurge [reportid#] (!) - if '!' is specified, acts on archive# instead\n" ); +      return qfalse; +    } +  } +   +  if( ID < 1 || +      ID > MAX_ADMIN_REPORTS || +      !g_admin_reports[ ID - 1 ] || +      ( g_admin_reports[ ID - 1 ]->expires != 0 && g_admin_reports[ ID - 1 ]->expires - t < 1 ) || +      g_admin_reports[ ID - 1 ]->closed != 0 ) +  { +    ADMP( "^3!rpurge: ^7invalid report#\n" ); +    return qfalse; +  } +   +  G_AdminsPrintf( va( "%s ^7purged report #%i\n",  +                    ( ent ) ? G_admin_adminPrintName( ent ) : "console",  +                    ID ) ); +  g_admin_reports[ ID - 1 ]->closed = 2; + +  if( g_report.string[ 0 ] ) +    admin_writeconfig(); + +  return qtrue; +} + +qboolean G_admin_rnote( gentity_t *ent, int skiparg ) +{ +  char *note; +  char tmp[ 2 ]; +  char arg2[ 5 ]; +  int ID; +   +  if( G_SayArgc() < 3 + skiparg ) +  { +    ADMP( "^3!rnote: ^7usage: !rnote [report#] (!) [note] - adding ! means rnote archive# instead of report#\n" ); +    return qfalse; +  } +   +  G_SayArgv( 1 + skiparg, arg2, sizeof( arg2 ) ); +  ID = atoi( arg2 ); +  G_SayArgv( 2 + skiparg, tmp, sizeof( tmp ) ); +  note = G_SayConcatArgs( 3 + skiparg ); +   +  if( !strcmp( tmp, "!" ) ) +    { +      if( ID < 1 || +          ID > MAX_ADMIN_ARCHIVES || +          !g_admin_archives[ ID - 1] ) +        { +          ADMP( "^3!rnote: ^7invalid archive#\n" ); +          return qfalse; +        } +         +        Q_strncpyz(g_admin_archives[ ID - 1 ]->note, +                   note, sizeof( g_admin_archives[ ID - 1 ]->note ) ); +        ADMP( va( "^5Note added to archive #%i\n", ID ) ); +        return qtrue; +    } else { +      note = G_SayConcatArgs( 2 + skiparg ); +    } +   +  if( ID < 1 || +      ID > MAX_ADMIN_REPORTS || +      !g_admin_reports[ ID - 1] ) +  { +    ADMP( "^3!rnote: ^7invalid report#\n" ); +    return qfalse; +  } +   +   +  ADMP( va( "^5Note added to report #%i\n", ID ) ); +  Q_strncpyz(g_admin_reports[ ID - 1 ]->note, +             note, sizeof( g_admin_reports[ ID - 1 ]->note ) ); + +  if( !g_admin.string[ 0 ] ) +    ADMP( "^3!rclose: ^7WARNING g_admin not set, not saving ban to a file\n" ); +  else +    admin_writeconfig(); +     +  return qtrue; +} + diff --git a/src/game/g_admin.h b/src/game/g_admin.h index 6e6e57a..d46b5fa 100644 --- a/src/game/g_admin.h +++ b/src/game/g_admin.h @@ -44,6 +44,10 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA  #define MAX_ADMIN_COMMANDS 64  #define MAX_ADMIN_CMD_LEN 20  #define MAX_ADMIN_BAN_REASON 50 +#define MAX_ADMIN_REPORTS 1024 +#define MAX_ADMIN_REPORTS_REASON 256 +#define MAX_ADMIN_ARCHIVES 1024 +#define MAX_ADMIN_ARCHIVES_REASON 256  #define MAX_ADMIN_BANSUSPEND_DAYS 14 @@ -93,12 +97,18 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA  #define ADMF_BAN_IMMUNITY        "BANIMMUNITY" +#define ADMF_FULLRLIST			 "FULLRLIST" +#define ADMF_NOREPORTLIMIT		 "NOREPORTLIMIT" +#define ADMF_SEESINCOGNITO		 "SEESINCOGNITO" +  #define ADMF_NO_CHAT             ".NOCHAT"  #define ADMF_NO_VOTE             ".NOVOTE"  #define MAX_ADMIN_LISTITEMS 20  #define MAX_ADMIN_SHOWBANS 10 +#define MAX_ADMIN_SHOWREPORTS 5 +  #define MAX_ADMIN_MAPLOG_LENGTH 5  // important note: QVM does not seem to allow a single char to be a @@ -197,6 +207,46 @@ typedef struct g_admin_tklog  }  g_admin_tklog_t; +typedef struct g_admin_report +{ +  char name[ 128 ]; +  char guid[ 33 ]; +  char ip[ 20 ]; +  char reason[ MAX_ADMIN_REPORTS_REASON ]; +  char map[ 50 ]; +  char time[ 48 ]; +  int players; +  char admins[ 256 ]; +  char rep[ 70 ]; +  char repIP[ 20 ]; +  char repGUID[ 33 ]; +  int level; +  char note[ MAX_ADMIN_REPORTS_REASON ]; +  int expires; +  int closed; +} +g_admin_report_t; + +typedef struct g_admin_archive +{ +  char name[ 128 ]; +  char guid[ 33 ]; +  char ip[ 20 ]; +  char reason[ MAX_ADMIN_REPORTS_REASON ]; +  char map[ 50 ]; +  char time[ 48 ]; +  int players; +  char admins[ 256 ]; +  char rep[ 70 ]; +  char repIP[ 20 ]; +  char repGUID[ 33 ]; +  int level; +  char note[ MAX_ADMIN_REPORTS_REASON ]; +  int expires; +} +g_admin_archive_t; +  +  qboolean G_admin_ban_check( char *userinfo, char *reason, int rlen );  qboolean G_admin_cmd_check( gentity_t *ent, qboolean say );  qboolean G_admin_readconfig( gentity_t *ent, int skiparg ); @@ -285,6 +335,14 @@ qboolean G_admin_slap( gentity_t *ent, int skiparg );  qboolean G_admin_drop( gentity_t *ent, int skiparg );  qboolean G_admin_bubble( gentity_t *ent, int skiparg ); +qboolean G_admin_report( gentity_t *ent, int skiparg ); +qboolean G_admin_rlist( gentity_t *ent, int skiparg ); +qboolean G_admin_rban( gentity_t *ent, int skiparg ); +qboolean G_admin_rarclist( gentity_t *ent, int skiparg ); +qboolean G_admin_rclose( gentity_t *ent, int skiparg ); +qboolean G_admin_rpurge( gentity_t *ent, int skiparg ); +qboolean G_admin_rnote( gentity_t *ent, int skiparg ); +  void G_admin_print( gentity_t *ent, char *m );  void G_admin_buffer_print( gentity_t *ent, char *m );  void G_admin_buffer_begin( void ); @@ -294,4 +352,6 @@ void G_admin_duration( int secs, char *duration, int dursize );  void G_admin_cleanup( void );  void G_admin_namelog_cleanup( void ); +void G_admin_report_check( int clientNum ); +  #endif /* ifndef _G_ADMIN_H */ diff --git a/src/game/g_client.c b/src/game/g_client.c index 6d8acfe..985c03d 100644 --- a/src/game/g_client.c +++ b/src/game/g_client.c @@ -1618,6 +1618,9 @@ void ClientBegin( int clientNum )      // rejoin any saved chat channels      G_admin_chat_sync( ent ); +	// report confirmation +	G_admin_report_check( clientNum ); +	      // request the clients PTR code      trap_SendServerCommand( ent - g_entities, "ptrcrequest" );    } diff --git a/src/game/g_cmds.c b/src/game/g_cmds.c index dad9cfe..723a2a5 100644 --- a/src/game/g_cmds.c +++ b/src/game/g_cmds.c @@ -1140,15 +1140,15 @@ void G_Say( gentity_t *ent, gentity_t *target, int mode, const char *chatText )        case SAY_ADMINS:          if( G_admin_permission( ent, ADMF_ADMINCHAT ) ) //Differentiate between inter-admin chatter and user-admin alerts          { -         G_LogPrintf( "say_admins: [ADMIN]%s^7: %s^7\n", ( ent ) ? ent->client->pers.netname : "console", chatText ); -         Com_sprintf( name, sizeof( name ), "%s[ADMIN]%s%c%c"EC": ", prefix, +         G_LogPrintf( "say_admins: ^7[^6ADMIN^7]%s^7: %s^7\n", ( ent ) ? ent->client->pers.netname : "console", chatText ); +         Com_sprintf( name, sizeof( name ), "%s^7[^6ADMIN^7]%s%c%c"EC": ", prefix,                      ( ent ) ? ent->client->pers.netname : "console", Q_COLOR_ESCAPE, COLOR_WHITE );           color = COLOR_MAGENTA;          }          else          { -          G_LogPrintf( "say_admins: [PLAYER]%s^7: %s^7\n", ent->client->pers.netname, chatText ); -          Com_sprintf( name, sizeof( name ), "%s[PLAYER]%s%c%c"EC": ", prefix, +          G_LogPrintf( "say_admins: ^7[^3PLAYER^7]%s^7: %s^7\n", ent->client->pers.netname, chatText ); +          Com_sprintf( name, sizeof( name ), "%s^7[^3PLAYER^7]%s%c%c"EC": ", prefix,              ent->client->pers.netname, Q_COLOR_ESCAPE, COLOR_WHITE );            color = COLOR_MAGENTA;          } @@ -2812,7 +2812,7 @@ void Cmd_CallTeamVote_f( gentity_t *ent )               ( ( !Q_stricmp( arg1, "kick" ) || !Q_stricmp( arg1, "denybuild" ) ) ||                level.clients[ i ].pers.teamSelection == PTE_NONE ) )      { -      trap_SendServerCommand( i, va("print \"^6[Admins]^7 %s " S_COLOR_WHITE +      trap_SendServerCommand( i, va("print \"^7[^5ADMIN^7] %s " S_COLOR_WHITE              "called a team vote: %s^7 \n\"", ent->client->pers.netname, level.teamVoteDisplayString[ cs_offset ] ) );      }    } @@ -5949,7 +5949,7 @@ void G_CP( gentity_t *ent )      {        if( G_admin_permission( &g_entities[ i ], ADMF_ADMINCHAT ) )        { -        trap_SendServerCommand( i, va("print \"^6[Admins]^7 CP to other team%s: %s \n\"", prefixes, text ) ); +        trap_SendServerCommand( i, va("print \"^7[^5ADMIN^7] CP to other team%s: %s \n\"", prefixes, text ) );        }        continue;      } diff --git a/src/game/g_local.h b/src/game/g_local.h index d51cf1b..09cce52 100644 --- a/src/game/g_local.h +++ b/src/game/g_local.h @@ -1448,6 +1448,7 @@ extern  vmCvar_t  g_layouts;  extern  vmCvar_t  g_layoutAuto;  extern  vmCvar_t  g_admin; +extern  vmCvar_t  g_report;  extern  vmCvar_t  g_adminLog;  extern  vmCvar_t  g_adminParseSay;  extern  vmCvar_t  g_adminSayFilter; @@ -1533,6 +1534,11 @@ extern  vmCvar_t  mod_jetpackFuel;  extern  vmCvar_t  mod_jetpackConsume;  extern  vmCvar_t  mod_jetpackRegen; +extern  vmCvar_t  g_maxReports; +extern  vmCvar_t  g_maxUnregReports; + +extern  vmCvar_t  g_reportWelcomeComment; +  void      trap_Printf( const char *fmt );  void      trap_Error( const char *fmt );  int       trap_Milliseconds( void ); diff --git a/src/game/g_main.c b/src/game/g_main.c index 105a95e..b535e73 100644 --- a/src/game/g_main.c +++ b/src/game/g_main.c @@ -183,6 +183,7 @@ vmCvar_t  g_layouts;  vmCvar_t  g_layoutAuto;  vmCvar_t  g_admin; +vmCvar_t  g_report;  vmCvar_t  g_adminLog;  vmCvar_t  g_adminParseSay;  vmCvar_t  g_adminSayFilter; @@ -274,6 +275,11 @@ vmCvar_t  mod_jetpackFuel;  vmCvar_t  mod_jetpackConsume;  vmCvar_t  mod_jetpackRegen; +vmCvar_t  g_maxReports; +vmCvar_t  g_maxUnregReports; + +vmCvar_t  g_reportWelcomeComment; +  static cvarTable_t   gameCvarTable[ ] =  {    // don't override the cheat state set by the system @@ -452,6 +458,7 @@ static cvarTable_t   gameCvarTable[ ] =    { &g_layoutAuto, "g_layoutAuto", "1", CVAR_ARCHIVE, 0, qfalse  },    { &g_admin, "g_admin", "admin.dat", CVAR_ARCHIVE, 0, qfalse  }, +  { &g_report, "g_report", "report.dat", CVAR_ARCHIVE, 0, qfalse  },    { &g_adminLog, "g_adminLog", "admin.log", CVAR_ARCHIVE, 0, qfalse  },    { &g_adminParseSay, "g_adminParseSay", "1", CVAR_ARCHIVE, 0, qfalse  },    { &g_adminSayFilter, "g_adminSayFilter", "0", CVAR_ARCHIVE, 0, qfalse  }, @@ -525,8 +532,12 @@ static cvarTable_t   gameCvarTable[ ] =    { &mod_jetpackFuel, "mod_jetpackFuel", "0", CVAR_ARCHIVE, 0, qfalse  },    { &mod_jetpackConsume, "mod_jetpackConsume", "2", CVAR_ARCHIVE, 0, qfalse  }, -  { &mod_jetpackRegen, "mod_jetpackRegen", "3", CVAR_ARCHIVE, 0, qfalse  } +  { &mod_jetpackRegen, "mod_jetpackRegen", "3", CVAR_ARCHIVE, 0, qfalse  }, + +  { &g_maxReports, "g_maxReports", "3", CVAR_ARCHIVE, 0, qfalse  }, +  { &g_maxUnregReports, "g_maxUnregReports", "1", CVAR_ARCHIVE, 0, qfalse  }, +  { &g_reportWelcomeComment, "g_reportWelcomeComment", "", CVAR_ARCHIVE, 0, qfalse }  };  static int gameCvarTableSize = sizeof( gameCvarTable ) / sizeof( gameCvarTable[ 0 ] ); @@ -2141,7 +2152,7 @@ void QDECL G_AdminsPrintf( const char *fmt, ... )      if( G_admin_permission( tempent, ADMF_ADMINCHAT) &&          !tempent->client->pers.ignoreAdminWarnings )       { -       trap_SendServerCommand(tempent-g_entities,va( "print \"^6[Admins]^7 %s\"", string) );  +       trap_SendServerCommand(tempent-g_entities,va( "print \"^7[^5ADMIN^7] %s\"", string) );       }    }  | 
