summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMaeJong <mewiceclair@gmail.com>2017-04-13 11:30:00 +0000
committer/dev/humancontroller <devhc@example.com>2017-04-15 17:24:21 +0200
commite86e59bfe6c3a31ec76d6dd4de22457b1a8f821a (patch)
tree80cf24129e2a55509e0e059a057878c331990aec
parent5fe4cc98914d6a35ae2247552565cb7e4fee3dda (diff)
Reports system
-rw-r--r--src/game/g_admin.c1644
-rw-r--r--src/game/g_admin.h60
-rw-r--r--src/game/g_client.c3
-rw-r--r--src/game/g_cmds.c12
-rw-r--r--src/game/g_local.h6
-rw-r--r--src/game/g_main.c15
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) );
}
}