summaryrefslogtreecommitdiff
path: root/src/game/g_admin.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/game/g_admin.c')
-rw-r--r--src/game/g_admin.c9006
1 files changed, 2105 insertions, 6901 deletions
diff --git a/src/game/g_admin.c b/src/game/g_admin.c
index dc19530..afc40cb 100644
--- a/src/game/g_admin.c
+++ b/src/game/g_admin.c
@@ -1,6 +1,7 @@
/*
===========================================================================
-Copyright (C) 2004-2006 Tony J. White
+Copyright (C) 2000-2013 Darklegion Development
+Copyright (C) 2015-2019 GrangerHub
This file is part of Tremulous.
@@ -11,12 +12,12 @@ and Travis Maurer.
The functionality of this code mimics the behaviour of the currently
inactive project shrubet (http://www.etstats.com/shrubet/index.php?ver=2)
-by Ryan Mannion. However, shrubet was a closed-source project and
-none of it's code has been copied, only it's functionality.
+by Ryan Mannion. However, shrubet was a closed-source project and
+none of its code has been copied, only its functionality.
Tremulous is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public License as
-published by the Free Software Foundation; either version 2 of the License,
+published by the Free Software Foundation; either version 3 of the License,
or (at your option) any later version.
Tremulous is distributed in the hope that it will be
@@ -25,8 +26,8 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
-along with Tremulous; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+along with Tremulous; if not, see <https://www.gnu.org/licenses/>
+
===========================================================================
*/
@@ -36,420 +37,270 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
static char g_bfb[ 32000 ];
// note: list ordered alphabetically
-g_admin_cmd_t g_admin_cmds[ ] =
- {
- {"adjustban", G_admin_adjustban, "ban",
- "change the duration or reason of a ban. time is specified as numbers "
- "followed by units 'w' (weeks), 'd' (days), 'h' (hours) or 'm' (minutes),"
- " or seconds if no units are specified. if the duration is"
- " preceded by a + or -, the ban duration will be extended or shortened by"
- " the specified amount",
- "[^3ban#^7] (^5duration^7) (^5reason^7)"
+g_admin_cmd_t g_admin_cmds[ ] =
+ {
+ {"addlayout", G_admin_addlayout, qfalse, "addlayout",
+ "place layout elements into the game. the elements are specified by a "
+ "union of filtered layouts. the syntax is demonstrated by an example: "
+ "^5reactor,telenode|westside+alien|sewers^7 will place only the "
+ "reactor and telenodes from the westside layout, and also all alien "
+ "layout elements from the sewers layout",
+ "[^3layoutelements^7]"
+ },
+
+ {"adjustban", G_admin_adjustban, qfalse, "ban",
+ "change the IP address mask, duration or reason of a ban. mask is "
+ "prefixed with '/'. duration is specified as numbers followed by units "
+ " 'w' (weeks), 'd' (days), 'h' (hours) or 'm' (minutes), or seconds if "
+ " no unit is specified. if the duration is preceded by a + or -, the "
+ "ban duration will be extended or shortened by the specified amount",
+ "[^3ban#^7] (^5/mask^7) (^5duration^7) (^5reason^7)"
},
-
- {"adminlog", G_admin_adminlog, "adminlog",
- "list recent admin activity",
- "(^5start id#|name|!command|-skip#^7) (^5search skip#^7)"
+
+ {"adminhelp", G_admin_adminhelp, qtrue, "adminhelp",
+ "display admin commands available to you or help on a specific command",
+ "(^5command^7)"
},
- {"admintest", G_admin_admintest, "admintest",
+ {"admintest", G_admin_admintest, qfalse, "admintest",
"display your current admin level",
""
},
- {"allowbuild", G_admin_denybuild, "denybuild",
+ {"allowbuild", G_admin_denybuild, qfalse, "denybuild",
"restore a player's ability to build",
"[^3name|slot#^7]"
},
- {"allowweapon", G_admin_denyweapon, "denyweapon",
- "restore a player's ability to use a weapon or class",
- "[^3name|slot#^7] [^3class|weapon|all^7]"
- },
-
- {"allready", G_admin_allready, "allready",
+ {"allready", G_admin_allready, qfalse, "allready",
"makes everyone ready in intermission",
""
},
- {"ban", G_admin_ban, "ban",
+ {"ban", G_admin_ban, qfalse, "ban",
"ban a player by IP and GUID with an optional expiration time and reason."
- " time is specified as numbers followed by units 'w' (weeks), 'd' "
+ " duration is specified as numbers followed by units 'w' (weeks), 'd' "
"(days), 'h' (hours) or 'm' (minutes), or seconds if no units are "
"specified",
- "[^3name|slot#|IP^7] (^5time^7) (^5reason^7)"
- },
-
- {"buildlog", G_admin_buildlog, "buildlog",
- "display a list of recent builds and deconstructs, optionally specifying"
- " a team",
- "(^5xnum^7) (^5#skip^7) (^5-name|num^7) (^5a|h^7)"
- "\n ^3Example:^7 '!buildlog #10 h' skips 10 events, then shows the previous 10 events affecting human buildables"
+ "[^3name|slot#|IP(/mask)^7] (^5duration^7) (^5reason^7)"
},
- {"cancelvote", G_admin_cancelvote, "cancelvote",
- "cancel a vote taking place",
+ {"builder", G_admin_builder, qtrue, "builder",
+ "show who built a structure",
""
},
-
- {"cp", G_admin_cp, "cp",
- "display a CP message to users, optionally specifying team(s) to send to",
- "(-AHS) [^3message^7]"
- },
- {"decon", G_admin_decon, "decon",
- "Reverts a decon previously made and ban the user for the time specified in g_deconBanTime",
- "[^3name|slot#^7]"
- },
-
- {"demo", G_admin_demo, "demo",
- "turn admin chat off for the caller so it does not appear in demos. "
- "this is a toggle use !demo again to turn warnings back on",
- ""
- },
-
- {"denybuild", G_admin_denybuild, "denybuild",
- "take away a player's ability to build",
- "[^3name|slot#^7]"
+ {"buildlog", G_admin_buildlog, qfalse, "buildlog",
+ "show buildable log",
+ "(^5name|slot#^7) (^5id^7)"
},
- {"designate", G_admin_designate, "designate",
- "give the player designated builder privileges",
- "[^3name|slot#^7]"
+ {"cancelvote", G_admin_endvote, qfalse, "cancelvote",
+ "cancel a vote taking place",
+ "(^5a|h^7)"
},
- {"devmap", G_admin_devmap, "devmap",
- "load a map with cheats (and optionally force layout)",
+ {"changemap", G_admin_changemap, qfalse, "changemap",
+ "load a map (and optionally force layout)",
"[^3mapname^7] (^5layout^7)"
},
- {"denyweapon", G_admin_denyweapon, "denyweapon",
- "take away a player's ability to use a weapon or class",
- "[^3name|slot#^7] [^3class|weapon^7]"
- },
-
- {"drop", G_admin_drop, "drop",
- "kick a client from the server without log",
- "[^3name|slot#^7] [^3message^7]"
- },
-
- {"flag", G_admin_flag, "flag",
- "add an admin flag to a player, prefix flag with '-' to disallow the flag. "
- "console can use this command on admin levels by prefacing a '*' to the admin level value.",
- "[^3name|slot#|admin#|*adminlevel^7] (^5+^7|^5-^7)[^3flag^7]"
- },
-
- {"flaglist", G_admin_flaglist, "flag",
- "list all flags understood by this server",
- ""
- },
-
- {"help", G_admin_help, "help",
- "display commands available to you or help on a specific command",
- "(^5command^7)"
+ {"denybuild", G_admin_denybuild, qfalse, "denybuild",
+ "take away a player's ability to build",
+ "[^3name|slot#^7]"
},
- {"info", G_admin_info, "info",
- "display the contents of server info files",
- "(^5subject^7)"
- },
-
- {"invisible", G_admin_invisible, "invisible",
- "hides a player so they cannot be seen in playerlists",
- ""
- },
-
- {"kick", G_admin_kick, "kick",
+ {"kick", G_admin_kick, qfalse, "kick",
"kick a player with an optional reason",
"[^3name|slot#^7] (^5reason^7)"
},
-
- {"L0", G_admin_L0, "l0",
- "Sets a level 1 to level 0",
- "[^3name|slot#^7]"
- },
-
- {"L1", G_admin_L1, "l1",
- "Sets a level 0 to level 1",
- "[^3name|slot#^7]"
- },
-
- {"layoutsave", G_admin_layoutsave, "layoutsave",
- "save a map layout",
- "[^3mapname^7]"
- },
-
- {"listadmins", G_admin_listadmins, "listadmins",
+
+ {"listadmins", G_admin_listadmins, qtrue, "listadmins",
"display a list of all server admins and their levels",
- "(^5name|start admin#^7) (^5minimum level to display^7)"
+ "(^5name^7) (^5start admin#^7)"
},
-
- {"listlayouts", G_admin_listlayouts, "listlayouts",
+
+ {"listlayouts", G_admin_listlayouts, qtrue, "listlayouts",
"display a list of all available layouts for a map",
"(^5mapname^7)"
},
- {"listplayers", G_admin_listplayers, "listplayers",
+ {"listplayers", G_admin_listplayers, qtrue, "listplayers",
"display a list of players, their client numbers and their levels",
""
},
-
- {"listmaps", G_admin_listmaps, "listmaps",
- "display a list of available maps on the server",
- "(^5map name^7)"
- },
-
- {"lock", G_admin_lock, "lock",
+
+ {"lock", G_admin_lock, qfalse, "lock",
"lock a team to prevent anyone from joining it",
"[^3a|h^7]"
},
-
- {"map", G_admin_map, "map",
- "load a map (and optionally force layout)",
- "[^3mapname^7] (^5layout^7)"
- },
- {"maplog", G_admin_maplog, "maplog",
- "show recently played maps",
- ""
- },
-
- {"mute", G_admin_mute, "mute",
+ {"mute", G_admin_mute, qfalse, "mute",
"mute a player",
- "[^3name|slot#^7] (Duration)"
+ "[^3name|slot#^7]"
},
-
- {"namelog", G_admin_namelog, "namelog",
+
+ {"namelog", G_admin_namelog, qtrue, "namelog",
"display a list of names used by recently connected players",
- "(^5name^7)"
+ "(^5name|IP(/mask)^7) (start namelog#)"
},
- {"nextmap", G_admin_nextmap, "nextmap",
+ {"nextmap", G_admin_nextmap, qfalse, "nextmap",
"go to the next map in the cycle",
""
},
- {"nobuild", G_admin_nobuild, "nobuild",
- "set nobuild markers to prevent players from building in an area",
- "(^5area^7) (^5height^7)"
+ {"passvote", G_admin_endvote, qfalse, "passvote",
+ "pass a vote currently taking place",
+ "(^5a|h^7)"
},
- {"passvote", G_admin_passvote, "passvote",
- "pass a vote currently taking place",
+ {"pause", G_admin_pause, qfalse, "pause",
+ "Pause (or unpause) the game.",
""
},
-
- {"pause", G_admin_pause, "pause",
- "prevent a player from interacting with the game."
- " * will pause all players, using no argument will pause game clock",
- "(^5name|slot|*^7)"
- },
-
- {"putteam", G_admin_putteam, "putteam",
+ {"putteam", G_admin_putteam, qfalse, "putteam",
"move a player to a specified team",
- "[^3name|slot#^7] [^3h|a|s^7] (^3duration^7)"
+ "[^3name|slot#^7] [^3h|a|s^7]"
},
- {"readconfig", G_admin_readconfig, "readconfig",
+ {"readconfig", G_admin_readconfig, qfalse, "readconfig",
"reloads the admin config file and refreshes permission flags",
""
},
-
- {"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.",
- ""
- },
- {"rename", G_admin_rename, "rename",
+ {"rename", G_admin_rename, qfalse, "rename",
"rename a player",
"[^3name|slot#^7] [^3new name^7]"
},
- {"restart", G_admin_restart, "restart",
+ {"restart", G_admin_restart, qfalse, "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"
+ {"revert", G_admin_revert, qfalse, "revert",
+ "revert buildables to a given time",
+ "[^3id^7]"
},
- {"rotation", G_admin_listrotation, "rotation",
- "display a list of maps that are in the active map rotation",
- ""
+ {"setdevmode", G_admin_setdevmode, qfalse, "setdevmode",
+ "switch developer mode on or off",
+ "[^3on|off^7]"
},
- {"seen", G_admin_seen, "seen",
- "find the last time a player was on the server",
- "[^3name|admin#^7]"
+ {"setivo", G_admin_setivo, qfalse, "setivo",
+ "set an intermission view override",
+ "[^3s|a|h^7]"
},
- {"setlevel", G_admin_setlevel, "setlevel",
+ {"setlevel", G_admin_setlevel, qfalse, "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)"
+ {"setnextmap", G_admin_setnextmap, qfalse, "setnextmap",
+ "set the next map (and, optionally, a forced layout)",
+ "[^3mapname^7] (^5layout^7)"
},
- {"slap", G_admin_slap, "slap",
- "Do damage to a player, and send them flying",
- "[^3name|slot^7] (damage)"
+ {"showbans", G_admin_showbans, qtrue, "showbans",
+ "display a (partial) list of active bans",
+ "(^5name|IP(/mask)^7) (^5start at ban#^7)"
},
- {"spec999", G_admin_spec999, "spec999",
+ {"spec999", G_admin_spec999, qfalse, "spec999",
"move 999 pingers to the spectator team",
- ""
- },
-
- {"specme", G_admin_putmespec, "specme",
- "moves you to the spectators",
- ""
- },
-
- {"subnetban", G_admin_subnetban, "subnetban",
- "Add or change a subnet mask on a ban",
- "[^3ban#^7] [^5CIDR mask^7]"
- "\n ^3Example:^7 '!subnetban 10 16' changes ban #10 to be a ban on XXX.XXX.*.*"
- "\n ^3Example:^7 '!subnetban 10 24' changes ban #10 to be a ban on XXX.XXX.XXX.*"
- "\n ^3Example:^7 '!subnetban 10 32' changes ban #10 to be a regular (non-subnet) ban"
- "\n ^1WARNING:^7 Use of this command may make your admin.dat incompatible with other game.qvms"
- },
-
- {"suspendban", G_admin_suspendban, "ban",
- "suspend a ban for a length of time. time is specified as numbers "
- "followed by units 'w' (weeks), 'd' (days), 'h' (hours) or 'm' (minutes),"
- " or seconds if no units are specified",
- "[^5ban #^7] [^5length^7]"
- },
+ ""},
- {"time", G_admin_time, "time",
+ {"time", G_admin_time, qtrue, "time",
"show the current local server time",
- ""
+ ""},
+ {"transform", G_admin_transform, qfalse, "magic",
+ "change a human player to a different player model",
+ "[^3name|slot#^7] [^3player model^7]"
},
- {"unban", G_admin_unban, "ban",
+ {"unban", G_admin_unban, qfalse, "ban",
"unbans a player specified by the slot as seen in showbans",
"[^3ban#^7]"
},
-
- {"undesignate", G_admin_designate, "designate",
- "revoke designated builder privileges",
- "[^3name|slot#^7]"
- },
-
- {"unflag", G_admin_flag, "flag",
- "clears an admin flag from a player. "
- "console can use this command on admin levels by prefacing a '*' to the admin level value.",
- "[^3name|slot#|admin#|*adminlevel^7] (^5+^7|^5-^7)[^3flag^7]"
- },
- {"unlock", G_admin_unlock, "lock",
+ {"unlock", G_admin_lock, qfalse, "lock",
"unlock a locked team",
"[^3a|h^7]"
},
-
- {"unmute", G_admin_mute, "mute",
+
+ {"unmute", G_admin_mute, qfalse, "mute",
"unmute a muted player",
"[^3name|slot#^7]"
},
- {"unpause", G_admin_pause, "pause",
- "allow a player to interact with the game."
- " * will unpause all players, using no argument will unpause game clock",
- "(^5name|slot|*^7)"
- },
-
- {
- "warn", G_admin_warn, "warn",
- "Warn a player to cease or face admin intervention",
- "[^3name|slot#^7] [reason]"
- },
-
- {"setdevmode", G_admin_setdevmode, "setdevmode",
- "switch developer mode on or off",
- "[^3on|off^7]"
- },
+ {"sm", G_admin_sm, qfalse, "schachtmeister",
+ "Schachtmeister",
+ "..."
+ }
+ };
- {"hstage", G_admin_hstage, "stage",
- "change the stage for humans",
- "[^3#^7]"
- },
+static size_t adminNumCmds = ARRAY_LEN( g_admin_cmds );
- {"astage", G_admin_astage, "stage",
- "change the stage for aliens",
- "[^3#^7]"
- },
+static int admin_level_maxname = 0;
+g_admin_level_t *g_admin_levels = NULL;
+g_admin_admin_t *g_admin_admins = NULL;
+g_admin_ban_t *g_admin_bans = NULL;
+g_admin_command_t *g_admin_commands = NULL;
- {"bubble", G_admin_bubble, "bubble",
- "continuously spawn bubbles around a player",
- "[^3name|slot#^7]"
- },
+void G_admin_register_cmds( void )
+{
+ int i;
- {"scrim", G_admin_scrim, "scrim",
- "toggles scrim mode",
- "[on|off]",
- },
+ for( i = 0; i < adminNumCmds; i++ )
+ trap_AddCommand( g_admin_cmds[ i ].keyword );
+}
- {"give", G_admin_give, "give",
- "give funds to a player",
- "[^3name|slot#^7] [^3amount^7]"
- },
+void G_admin_unregister_cmds( void )
+{
+ int i;
- {"setrotation", G_admin_setrotation, "setrotation",
- "sets the map rotation",
- "[^3rotation^7]"
- },
+ for( i = 0; i < adminNumCmds; i++ )
+ trap_RemoveCommand( g_admin_cmds[ i ].keyword );
+}
- {"versions", G_admin_versions, "namelog",
- "Check what versions of Tremulous players are running.",
- ""
- },
+void G_admin_cmdlist( gentity_t *ent )
+{
+ int i;
+ char out[ MAX_STRING_CHARS ] = "";
+ int len, outlen;
- {"showff", G_admin_showff, "showff",
- "shows how much friendly damage a player has done this game"
- "\nno arguments will list all connected players",
- "(^3name|slot^7)"
- "\n ^3Example:^7 ^120% ^7means 1/5th of the damage dealt this game was dealt to the team"
- },
+ outlen = 0;
- {"tklog", G_admin_tklog, "tklog",
- "list recent teamkill activity",
- "(^5start id#|name|-skip#^7) (^5search skip#^7)"
- },
+ for( i = 0; i < adminNumCmds; i++ )
+ {
+ if( !G_admin_permission( ent, g_admin_cmds[ i ].flag ) )
+ continue;
- {"sm", G_admin_sm, "schachtmeister",
- "Schachtmeister",
- "..."
+ len = strlen( g_admin_cmds[ i ].keyword ) + 1;
+ if( len + outlen >= sizeof( out ) - 1 )
+ {
+ trap_SendServerCommand( ent - g_entities, va( "cmds%s\n", out ) );
+ outlen = 0;
}
- };
-
-static int adminNumCmds = sizeof( g_admin_cmds ) / sizeof( g_admin_cmds[ 0 ] );
-
-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_command_t *g_admin_commands[ MAX_ADMIN_COMMANDS ];
-g_admin_namelog_t *g_admin_namelog[ MAX_ADMIN_NAMELOGS ];
+ strcpy( out + outlen, va( " %s", g_admin_cmds[ i ].keyword ) );
+ outlen += len;
+ }
-int G_admin_parse_time( const char *time );
+ trap_SendServerCommand( ent - g_entities, va( "cmds%s\n", out ) );
+}
// match a certain flag within these flags
-// return state of whether flag was found or not,
-// set *perm to indicate whether found flag was + or -
static qboolean admin_permission( char *flags, const char *flag, qboolean *perm )
{
char *token, *token_p = flags;
- qboolean all_found = qfalse;
- qboolean base_perm = qfalse;
-
+ qboolean allflags = qfalse;
+ qboolean p = qfalse;
+ *perm = qfalse;
while( *( token = COM_Parse( &token_p ) ) )
{
*perm = qtrue;
@@ -459,63 +310,84 @@ static qboolean admin_permission( char *flags, const char *flag, qboolean *perm
return qtrue;
if( !strcmp( token, ADMF_ALLFLAGS ) )
{
- all_found = qtrue;
- base_perm = *perm;
+ allflags = qtrue;
+ p = *perm;
}
}
+ if( allflags )
+ *perm = p;
+ return allflags;
+}
+
+g_admin_cmd_t *G_admin_cmd( const char *cmd )
+{
+ return bsearch( cmd, g_admin_cmds, adminNumCmds, sizeof( g_admin_cmd_t ),
+ cmdcmp );
+}
+
+g_admin_level_t *G_admin_level( const int l )
+{
+ g_admin_level_t *level;
- if( all_found && flag[ 0 ] != '.' )
+ for( level = g_admin_levels; level; level = level->next )
{
- *perm = base_perm;
- return qtrue;
+ if( level->level == l )
+ return level;
}
- return qfalse;
+ return NULL;
}
-static int admin_adminlog_index = 0;
-g_admin_adminlog_t *g_admin_adminlog[ MAX_ADMIN_ADMINLOGS ];
-
-static int admin_tklog_index = 0;
-g_admin_tklog_t *g_admin_tklog[ MAX_ADMIN_TKLOGS ];
-
-// This function should only be used directly when the client is connecting and thus has no GUID.
-// Else, use G_admin_permission()
-qboolean G_admin_permission_guid( char *guid, const char* flag )
+g_admin_admin_t *G_admin_admin( const char *guid )
{
- int i;
- int l = 0;
- qboolean perm = qfalse;
+ g_admin_admin_t *admin;
- // Does the admin specifically have this flag granted/denied to them,
- // irrespective of their admin level?
- for( i = 0; i < MAX_ADMIN_ADMINS && g_admin_admins[ i ]; i++ )
+ for( admin = g_admin_admins; admin; admin = admin->next )
{
- if( !Q_stricmp( guid, g_admin_admins[ i ]->guid ) )
- {
- if( admin_permission( g_admin_admins[ i ]->flags, flag, &perm ) )
- return perm;
- l = g_admin_admins[ i ]->level;
- break;
- }
+ if( !Q_stricmp( admin->guid, guid ) )
+ return admin;
}
- // If not, is this flag granted/denied for their admin level?
- for( i = 0; i < MAX_ADMIN_LEVELS && g_admin_levels[ i ]; i++ )
+ return NULL;
+}
+
+g_admin_command_t *G_admin_command( const char *cmd )
+{
+ g_admin_command_t *c;
+
+ for( c = g_admin_commands; c; c = c->next )
{
- if( g_admin_levels[ i ]->level == l )
- return admin_permission( g_admin_levels[ i ]->flags, flag, &perm ) &&
- perm;
+ if( !Q_stricmp( c->command, cmd ) )
+ return c;
}
- return qfalse;
-}
+ return NULL;
+}
qboolean G_admin_permission( gentity_t *ent, const char *flag )
{
- if(!ent) return qtrue; //console always wins
+ qboolean perm;
+ g_admin_admin_t *a;
+ g_admin_level_t *l;
+
+ // console always wins
+ if( !ent )
+ return qtrue;
+
+ if( ( a = ent->client->pers.admin ) )
+ {
+ if( admin_permission( a->flags, flag, &perm ) )
+ return perm;
+
+ l = G_admin_level( a->level );
+ }
+ else
+ l = G_admin_level( 0 );
+
+ if( l )
+ return admin_permission( l->flags, flag, &perm ) && perm;
- return G_admin_permission_guid(ent->client->pers.guid, flag);
+ return qfalse;
}
qboolean G_admin_name_check( gentity_t *ent, char *name, char *err, int len )
@@ -524,125 +396,94 @@ qboolean G_admin_name_check( gentity_t *ent, char *name, char *err, int len )
gclient_t *client;
char testName[ MAX_NAME_LENGTH ] = {""};
char name2[ MAX_NAME_LENGTH ] = {""};
+ g_admin_admin_t *admin;
int alphaCount = 0;
- G_SanitiseString( name, name2, sizeof( name2) );
+ G_SanitiseString( name, name2, sizeof( name2 ) );
- if( !Q_stricmp( name2, "UnnamedPlayer" ) )
+ if( !strcmp( name2, "unnamedplayer" ) )
return qtrue;
- if( !Q_stricmp( name2, "console" ) )
+ if( !strcmp( name2, "console" ) )
+ {
+ if( err && len > 0 )
+ Q_strncpyz( err, "The name 'console' is not allowed.", len );
+ return qfalse;
+ }
+
+ G_DecolorString( name, testName, sizeof( testName ) );
+ if( isdigit( testName[ 0 ] ) )
{
- Q_strncpyz( err, va( "The name '%s^7' is invalid here", name2 ),
- len );
+ if( err && len > 0 )
+ Q_strncpyz( err, "Names cannot begin with numbers", len );
+ return qfalse;
+ }
+
+ for( i = 0; testName[ i ]; i++)
+ {
+ if( isalpha( testName[ i ] ) )
+ alphaCount++;
+ }
+
+ if( alphaCount == 0 )
+ {
+ if( err && len > 0 )
+ Q_strncpyz( err, "Names must contain letters", len );
return qfalse;
}
for( i = 0; i < level.maxclients; i++ )
{
client = &level.clients[ i ];
- if( client->pers.connected != CON_CONNECTING
- && client->pers.connected != CON_CONNECTED )
- {
+ if( client->pers.connected == CON_DISCONNECTED )
continue;
- }
// can rename ones self to the same name using different colors
if( i == ( ent - g_entities ) )
continue;
- G_SanitiseString( client->pers.netname, testName, sizeof( testName) );
- if( !Q_stricmp( name2, testName ) )
+ G_SanitiseString( client->pers.netname, testName, sizeof( testName ) );
+ if( !strcmp( name2, testName ) )
{
- Q_strncpyz( err, va( "The name '%s^7' is already in use", name ),
- len );
+ if( err && len > 0 )
+ Com_sprintf( err, len, "The name '%s^7' is already in use", name );
return qfalse;
}
}
-
- if( Q_isdigit( name2[ 0 ] ) || name2[ 0 ] == '-' )
- {
- Q_strncpyz( err, "Names cannot begin with a number or with a dash. Please choose another.", len );
- return qfalse;
- }
-
- for( i = 0; name2[ i ] !='\0'; i++)
- {
- if( Q_isalpha( name2[ i ] ) )
- alphaCount++;
- if( name2[ i ] == ' ' )
- {
- if( name2[ i + 1 ] == '-' )
- {
- Q_strncpyz( err, "Names cannot contain a - preceded by a space. Please choose another.", len );
- return qfalse;
- }
- }
- }
-
- if( alphaCount == 0 )
+ for( admin = g_admin_admins; admin; admin = admin->next )
{
- Q_strncpyz( err, va( "The name '%s^7' does not include at least one letter. Please choose another.", name ), len );
- return qfalse;
- }
-
- if( !g_adminNameProtect.string[ 0 ] )
- return qtrue;
-
- for( i = 0; i < MAX_ADMIN_ADMINS && g_admin_admins[ i ]; i++ )
- {
- if( g_admin_admins[ i ]->level < 1 )
+ if( admin->level < 1 )
continue;
- G_SanitiseString( g_admin_admins[ i ]->name, testName, sizeof( testName) );
- if( !Q_stricmp( name2, testName ) &&
- Q_stricmp( ent->client->pers.guid, g_admin_admins[ i ]->guid ) )
+ G_SanitiseString( admin->name, testName, sizeof( testName ) );
+ if( !strcmp( name2, testName ) && ent->client->pers.admin != admin )
{
- Q_strncpyz( err, va( "The name '%s^7' belongs to an admin. "
- "Please choose another.", name ), len );
+ if( err && len > 0 )
+ Com_sprintf( err, len, "The name '%s^7' belongs to an admin, "
+ "please use another name", name );
return qfalse;
}
}
return qtrue;
}
-static qboolean admin_higher_guid( char *admin_guid, char *victim_guid )
+static qboolean admin_higher_admin( g_admin_admin_t *a, g_admin_admin_t *b )
{
- int i;
- int alevel = 0;
- int alevel2 = 0;
-
- for( i = 0; i < MAX_ADMIN_ADMINS && g_admin_admins[ i ]; i++ )
- {
- if( !Q_stricmp( admin_guid, g_admin_admins[ i ]->guid ) )
- {
- alevel = g_admin_admins[ i ]->level;
-
- // Novelty Levels should be equivelant to level 1
- if( alevel > 9 )
- alevel = 1;
+ qboolean perm;
- break;
- }
- }
- for( i = 0; i < MAX_ADMIN_ADMINS && g_admin_admins[ i ]; i++ )
- {
- if( !Q_stricmp( victim_guid, g_admin_admins[ i ]->guid ) )
- {
- alevel2 = g_admin_admins[ i ]->level;
+ if( !b )
+ return qtrue;
- // Novelty Levels should be equivelant to level 1
- if( alevel2 > 9 )
- alevel2 = 1;
+ if( admin_permission( b->flags, ADMF_IMMUTABLE, &perm ) )
+ return !perm;
- if( alevel < alevel2 )
- return qfalse;
+ return b->level <= ( a ? a->level : 0 );
+}
- if( strstr( g_admin_admins[ i ]->flags, va( "%s", ADMF_IMMUTABLE ) ) )
- return qfalse;
- }
- }
- return qtrue;
+static qboolean admin_higher_guid( char *admin_guid, char *victim_guid )
+{
+ return admin_higher_admin( G_admin_admin( admin_guid ),
+ G_admin_admin( victim_guid ) );
}
static qboolean admin_higher( gentity_t *admin, gentity_t *victim )
@@ -651,25 +492,15 @@ static qboolean admin_higher( gentity_t *admin, gentity_t *victim )
// console always wins
if( !admin )
return qtrue;
- // just in case
- if( !victim )
- return qtrue;
- return admin_higher_guid( admin->client->pers.guid,
- victim->client->pers.guid );
+ return admin_higher_admin( admin->client->pers.admin,
+ victim->client->pers.admin );
}
static void admin_writeconfig_string( char *s, fileHandle_t f )
{
- char buf[ MAX_STRING_CHARS ];
-
- buf[ 0 ] = '\0';
if( s[ 0 ] )
- {
- //Q_strcat(buf, sizeof(buf), s);
- Q_strncpyz( buf, s, sizeof( buf ) );
- trap_FS_Write( buf, strlen( buf ), f );
- }
+ trap_FS_Write( s, strlen( s ), f );
trap_FS_Write( "\n", 1, f );
}
@@ -677,18 +508,18 @@ static void admin_writeconfig_int( int v, fileHandle_t f )
{
char buf[ 32 ];
- Com_sprintf( buf, sizeof(buf), "%d", v );
- if( buf[ 0 ] )
- trap_FS_Write( buf, strlen( buf ), f );
- trap_FS_Write( "\n", 1, f );
+ Com_sprintf( buf, sizeof( buf ), "%d\n", v );
+ trap_FS_Write( buf, strlen( buf ), f );
}
-void admin_writeconfig( void )
+static void admin_writeconfig( void )
{
fileHandle_t f;
- int len, i;
- int t, expiretime;
- char levels[ MAX_STRING_CHARS ] = {""};
+ int t;
+ g_admin_admin_t *a;
+ g_admin_level_t *l;
+ g_admin_ban_t *b;
+ g_admin_command_t *c;
if( !g_admin.string[ 0 ] )
{
@@ -697,96 +528,75 @@ void admin_writeconfig( void )
return;
}
t = trap_RealTime( NULL );
- len = trap_FS_FOpenFile( g_admin.string, &f, FS_WRITE );
- if( len < 0 )
+ if( trap_FS_FOpenFile( g_admin.string, &f, FS_WRITE ) < 0 )
{
G_Printf( "admin_writeconfig: could not open g_admin file \"%s\"\n",
g_admin.string );
return;
}
- for( i = 0; i < MAX_ADMIN_LEVELS && g_admin_levels[ i ]; i++ )
+ for( l = g_admin_levels; l; l = l->next )
{
trap_FS_Write( "[level]\n", 8, f );
trap_FS_Write( "level = ", 10, f );
- admin_writeconfig_int( g_admin_levels[ i ]->level, f );
+ admin_writeconfig_int( l->level, f );
trap_FS_Write( "name = ", 10, f );
- admin_writeconfig_string( g_admin_levels[ i ]->name, f );
+ admin_writeconfig_string( l->name, f );
trap_FS_Write( "flags = ", 10, f );
- admin_writeconfig_string( g_admin_levels[ i ]->flags, f );
+ admin_writeconfig_string( l->flags, f );
trap_FS_Write( "\n", 1, f );
}
- for( i = 0; i < MAX_ADMIN_ADMINS && g_admin_admins[ i ]; i++ )
+ for( a = g_admin_admins; a; a = a->next )
{
// don't write level 0 users
- if( g_admin_admins[ i ]->level < 1 )
+ if( a->level == 0 )
continue;
- //if set dont write admins that havent been seen in a while
- expiretime = G_admin_parse_time( g_adminExpireTime.string );
- if( expiretime > 0 ) {
- //only expire level 1 people
- if( t - expiretime > g_admin_admins[ i ]->seen && g_admin_admins[ i ]->level == 1 ) {
- G_Printf("Admin %s has been expired.\n", g_admin_admins[ i ]->name );
- continue;
- }
- }
-
trap_FS_Write( "[admin]\n", 8, f );
trap_FS_Write( "name = ", 10, f );
- admin_writeconfig_string( g_admin_admins[ i ]->name, f );
+ admin_writeconfig_string( a->name, f );
trap_FS_Write( "guid = ", 10, f );
- admin_writeconfig_string( g_admin_admins[ i ]->guid, f );
+ admin_writeconfig_string( a->guid, f );
trap_FS_Write( "level = ", 10, f );
- admin_writeconfig_int( g_admin_admins[ i ]->level, f );
+ admin_writeconfig_int( a->level, f );
trap_FS_Write( "flags = ", 10, f );
- admin_writeconfig_string( g_admin_admins[ i ]->flags, f );
- trap_FS_Write( "seen = ", 10, f );
- admin_writeconfig_int( g_admin_admins[ i ]->seen, f );
+ admin_writeconfig_string( a->flags, f );
trap_FS_Write( "\n", 1, f );
}
- for( i = 0; i < MAX_ADMIN_BANS && g_admin_bans[ i ]; i++ )
+ for( b = g_admin_bans; b; b = b->next )
{
// don't write expired bans
// if expires is 0, then it's a perm ban
- if( g_admin_bans[ i ]->expires != 0 &&
- ( g_admin_bans[ i ]->expires - t ) < 1 )
+ if( b->expires != 0 && b->expires <= t )
continue;
trap_FS_Write( "[ban]\n", 6, f );
trap_FS_Write( "name = ", 10, f );
- admin_writeconfig_string( g_admin_bans[ i ]->name, f );
+ admin_writeconfig_string( b->name, f );
trap_FS_Write( "guid = ", 10, f );
- admin_writeconfig_string( g_admin_bans[ i ]->guid, f );
+ admin_writeconfig_string( b->guid, f );
trap_FS_Write( "ip = ", 10, f );
- admin_writeconfig_string( g_admin_bans[ i ]->ip, f );
+ admin_writeconfig_string( b->ip.str, f );
trap_FS_Write( "reason = ", 10, f );
- admin_writeconfig_string( g_admin_bans[ i ]->reason, f );
+ admin_writeconfig_string( b->reason, f );
trap_FS_Write( "made = ", 10, f );
- admin_writeconfig_string( g_admin_bans[ i ]->made, f );
+ admin_writeconfig_string( b->made, f );
trap_FS_Write( "expires = ", 10, f );
- admin_writeconfig_int( g_admin_bans[ i ]->expires, f );
- if( g_admin_bans[ i ]->suspend > t ) {
- trap_FS_Write( "suspend = ", 10, f );
- admin_writeconfig_int( g_admin_bans[ i ]->suspend, f );
- }
+ admin_writeconfig_int( b->expires, f );
trap_FS_Write( "banner = ", 10, f );
- admin_writeconfig_string( g_admin_bans[ i ]->banner, f );
- trap_FS_Write( "blevel = ", 10, f );
- admin_writeconfig_int( g_admin_bans[ i ]->bannerlevel, f );
+ admin_writeconfig_string( b->banner, f );
trap_FS_Write( "\n", 1, f );
}
- for( i = 0; i < MAX_ADMIN_COMMANDS && g_admin_commands[ i ]; i++ )
+ for( c = g_admin_commands; c; c = c->next )
{
- levels[ 0 ] = '\0';
trap_FS_Write( "[command]\n", 10, f );
trap_FS_Write( "command = ", 10, f );
- admin_writeconfig_string( g_admin_commands[ i ]->command, f );
+ admin_writeconfig_string( c->command, f );
trap_FS_Write( "exec = ", 10, f );
- admin_writeconfig_string( g_admin_commands[ i ]->exec, f );
+ admin_writeconfig_string( c->exec, f );
trap_FS_Write( "desc = ", 10, f );
- admin_writeconfig_string( g_admin_commands[ i ]->desc, f );
+ admin_writeconfig_string( c->desc, f );
trap_FS_Write( "flag = ", 10, f );
- admin_writeconfig_string( g_admin_commands[ i ]->flag, f );
+ admin_writeconfig_string( c->flag, f );
trap_FS_Write( "\n", 1, f );
}
trap_FS_FCloseFile( f );
@@ -794,41 +604,32 @@ void admin_writeconfig( void )
static void admin_readconfig_string( char **cnf, char *s, int size )
{
- char * t;
+ char *t;
//COM_MatchToken(cnf, "=");
+ s[ 0 ] = '\0';
t = COM_ParseExt( cnf, qfalse );
- if( !strcmp( t, "=" ) )
- {
- t = COM_ParseExt( cnf, qfalse );
- }
- else
+ if( strcmp( t, "=" ) )
{
- G_Printf( "readconfig: warning missing = before "
- "\"%s\" on line %d\n",
- t,
- COM_GetCurrentParseLine() );
+ COM_ParseWarning( "expected '=' before \"%s\"", t );
+ Q_strncpyz( s, t, size );
}
- s[ 0 ] = '\0';
- while( t[ 0 ] )
+ while( 1 )
{
- if( ( s[ 0 ] == '\0' && strlen( t ) <= size )
- || ( strlen( t ) + strlen( s ) < size ) )
- {
-
- Q_strcat( s, size, t );
- Q_strcat( s, size, " " );
- }
t = COM_ParseExt( cnf, qfalse );
+ if( !*t )
+ break;
+ if( strlen( t ) + strlen( s ) >= size )
+ break;
+ if( *s )
+ Q_strcat( s, size, " " );
+ Q_strcat( s, size, t );
}
- // trim the trailing space
- if( strlen( s ) > 0 && s[ strlen( s ) - 1 ] == ' ' )
- s[ strlen( s ) - 1 ] = '\0';
}
static void admin_readconfig_int( char **cnf, int *v )
{
- char * t;
+ char *t;
//COM_MatchToken(cnf, "=");
t = COM_ParseExt( cnf, qfalse );
@@ -838,10 +639,7 @@ static void admin_readconfig_int( char **cnf, int *v )
}
else
{
- G_Printf( "readconfig: warning missing = before "
- "\"%s\" on line %d\n",
- t,
- COM_GetCurrentParseLine() );
+ COM_ParseWarning( "expected '=' before \"%s\"", t );
}
*v = atoi( t );
}
@@ -850,413 +648,217 @@ static void admin_readconfig_int( char **cnf, int *v )
// ones to make new installs easier for admins
static void admin_default_levels( void )
{
- g_admin_level_t * l;
- int i;
-
- for( i = 0; i < MAX_ADMIN_LEVELS && g_admin_levels[ i ]; i++ )
- {
- G_Free( g_admin_levels[ i ] );
- g_admin_levels[ i ] = NULL;
- }
- for( i = 0; i <= 5; i++ )
- {
- l = G_Alloc( sizeof( g_admin_level_t ) );
- l->level = i;
- *l->name = '\0';
- *l->flags = '\0';
- g_admin_levels[ i ] = l;
- }
+ g_admin_level_t *l;
+ int level = 0;
- Q_strncpyz( g_admin_levels[ 0 ]->name, "^4Unknown Player",
- sizeof( l->name ) );
- Q_strncpyz( g_admin_levels[ 0 ]->flags,
- "listplayers admintest help specme time",
+ l = g_admin_levels = BG_Alloc( sizeof( g_admin_level_t ) );
+ l->level = level++;
+ Q_strncpyz( l->name, "^4Unknown Player", sizeof( l->name ) );
+ Q_strncpyz( l->flags,
+ "listplayers admintest adminhelp time",
sizeof( l->flags ) );
- Q_strncpyz( g_admin_levels[ 1 ]->name, "^5Server Regular",
- sizeof( l->name ) );
- Q_strncpyz( g_admin_levels[ 1 ]->flags,
- "listplayers admintest help specme time",
+ l = l->next = BG_Alloc( sizeof( g_admin_level_t ) );
+ l->level = level++;
+ Q_strncpyz( l->name, "^5Server Regular", sizeof( l->name ) );
+ Q_strncpyz( l->flags,
+ "listplayers admintest adminhelp time",
sizeof( l->flags ) );
- Q_strncpyz( g_admin_levels[ 2 ]->name, "^6Team Manager",
- sizeof( l->name ) );
- Q_strncpyz( g_admin_levels[ 2 ]->flags,
- "listplayers admintest help specme time putteam spec999 warn denybuild",
+ l = l->next = BG_Alloc( sizeof( g_admin_level_t ) );
+ l->level = level++;
+ Q_strncpyz( l->name, "^6Team Manager", sizeof( l->name ) );
+ Q_strncpyz( l->flags,
+ "listplayers admintest adminhelp time putteam spec999",
sizeof( l->flags ) );
- Q_strncpyz( g_admin_levels[ 3 ]->name, "^2Junior Admin",
- sizeof( l->name ) );
- Q_strncpyz( g_admin_levels[ 3 ]->flags,
- "listplayers admintest help specme time putteam spec999 kick mute warn "
- "denybuild ADMINCHAT SEESFULLLISTPLAYERS",
+ l = l->next = BG_Alloc( sizeof( g_admin_level_t ) );
+ l->level = level++;
+ Q_strncpyz( l->name, "^2Junior Admin", sizeof( l->name ) );
+ Q_strncpyz( l->flags,
+ "listplayers admintest adminhelp time putteam spec999 kick mute ADMINCHAT",
sizeof( l->flags ) );
- Q_strncpyz( g_admin_levels[ 4 ]->name, "^3Senior Admin",
- sizeof( l->name ) );
- Q_strncpyz( g_admin_levels[ 4 ]->flags,
- "listplayers admintest help specme time putteam spec999 kick mute showbans "
- "ban namelog warn denybuild decon ADMINCHAT SEESFULLLISTPLAYERS",
+ l = l->next = BG_Alloc( sizeof( g_admin_level_t ) );
+ l->level = level++;
+ Q_strncpyz( l->name, "^3Senior Admin", sizeof( l->name ) );
+ Q_strncpyz( l->flags,
+ "listplayers admintest adminhelp time putteam spec999 kick mute showbans ban "
+ "namelog ADMINCHAT",
sizeof( l->flags ) );
- Q_strncpyz( g_admin_levels[ 5 ]->name, "^1Server Operator",
- sizeof( l->name ) );
- Q_strncpyz( g_admin_levels[ 5 ]->flags,
- "ALLFLAGS -INCOGNITO -IMMUTABLE -DBUILDER -BANIMMUNITY",
+ l = l->next = BG_Alloc( sizeof( g_admin_level_t ) );
+ l->level = level++;
+ Q_strncpyz( l->name, "^1Server Operator", sizeof( l->name ) );
+ Q_strncpyz( l->flags,
+ "ALLFLAGS -IMMUTABLE -INCOGNITO",
sizeof( l->flags ) );
+ admin_level_maxname = 15;
}
-// return a level for a player entity.
-int G_admin_level( gentity_t *ent )
+void G_admin_authlog( gentity_t *ent )
{
- int i;
- qboolean found = qfalse;
+ char aflags[ MAX_ADMIN_FLAGS * 2 ];
+ g_admin_level_t *level;
+ int levelNum = 0;
if( !ent )
- {
- return MAX_ADMIN_LEVELS;
- }
+ return;
- for( i = 0; i < MAX_ADMIN_ADMINS && g_admin_admins[ i ]; i++ )
- {
- if( !Q_stricmp( g_admin_admins[ i ]->guid, ent->client->pers.guid ) )
- {
+ if( ent->client->pers.admin )
+ levelNum = ent->client->pers.admin->level;
- found = qtrue;
- break;
- }
- }
+ level = G_admin_level( levelNum );
- if( found )
- {
- return g_admin_admins[ i ]->level;
- }
+ Com_sprintf( aflags, sizeof( aflags ), "%s %s",
+ ent->client->pers.admin->flags,
+ ( level ) ? level->flags : "" );
- return 0;
+ G_LogPrintf( "AdminAuth: %i \"%s" S_COLOR_WHITE "\" \"%s" S_COLOR_WHITE
+ "\" [%d] (%s): %s\n",
+ (int)( ent - g_entities ), ent->client->pers.netname,
+ ent->client->pers.admin->name, ent->client->pers.admin->level,
+ ent->client->pers.guid, aflags );
}
-// set a player's adminname
-void G_admin_set_adminname( gentity_t *ent )
+static char adminLog[ MAX_STRING_CHARS ];
+static int adminLogLen;
+static void admin_log_start( gentity_t *admin, const char *cmd )
{
- int i;
- qboolean found = qfalse;
+ const char *name = admin ? admin->client->pers.netname : "console";
- if( !ent )
- {
- return;
- }
-
- for( i = 0; i < MAX_ADMIN_ADMINS && g_admin_admins[ i ]; i++ )
- {
- if( !Q_stricmp( g_admin_admins[ i ]->guid, ent->client->pers.guid ) )
- {
- found = qtrue;
- break;
- }
- }
-
- if( found )
- {
- Q_strncpyz( ent->client->pers.adminName, g_admin_admins[ i ]->name, sizeof( ent->client->pers.adminName ) );
- }
- else
- {
- Q_strncpyz( ent->client->pers.adminName, "", sizeof( ent->client->pers.adminName ) );
- }
+ adminLogLen = Q_snprintf( adminLog, sizeof( adminLog ),
+ "%d \"%s" S_COLOR_WHITE "\" \"%s" S_COLOR_WHITE "\" [%d] (%s): %s",
+ admin ? admin->s.clientNum : -1,
+ name,
+ admin && admin->client->pers.admin ? admin->client->pers.admin->name : name,
+ admin && admin->client->pers.admin ? admin->client->pers.admin->level : 0,
+ admin ? admin->client->pers.guid : "",
+ cmd );
}
-// Get an admin's registered name
-const char *G_admin_get_adminname( gentity_t *ent )
+static void admin_log( const char *str )
{
- int i;
-
- if( !ent )
- return "console";
-
- for( i = 0; i < MAX_ADMIN_ADMINS && g_admin_admins[ i ]; i++ )
- {
- if( !Q_stricmp( g_admin_admins[ i ]->guid, ent->client->pers.guid ) )
- return g_admin_admins[ i ]->name;
- }
-
- return ent->client->pers.netname;
+ if( adminLog[ 0 ] )
+ adminLogLen += Q_snprintf( adminLog + adminLogLen,
+ sizeof( adminLog ) - adminLogLen, ": %s", str );
}
-// Get an admin's name to print as the user of various commands,
-// obeying admin stealth settings when necessary
-char* G_admin_adminPrintName( gentity_t *ent )
+static void admin_log_abort( void )
{
- char *out;
-
- if( !ent->client->pers.adminLevel )
- {
- out = "";
- return out;
- }
-
- if( G_admin_permission( ent, ADMF_ADMINSTEALTH ) )
- {
- out = ent->client->pers.adminName;
- }
- else
- {
- out = ent->client->pers.netname;
- }
-
-
- return out;
+ adminLog[ 0 ] = '\0';
+ adminLogLen = 0;
}
-static void admin_log( gentity_t *admin, char *cmd, int skiparg )
+static void admin_log_end( const qboolean ok )
{
- fileHandle_t f;
- int len, i, j;
- char string[ MAX_STRING_CHARS ], decoloured[ MAX_STRING_CHARS ];
- int min, tens, sec;
- g_admin_admin_t *a;
- g_admin_level_t *l;
- char flags[ MAX_ADMIN_FLAGS * 2 ];
- gentity_t *victim = NULL;
- int pids[ MAX_CLIENTS ];
- char name[ MAX_NAME_LENGTH ];
-
- if( !g_adminLog.string[ 0 ] )
- return ;
-
-
- len = trap_FS_FOpenFile( g_adminLog.string, &f, FS_APPEND );
- if( len < 0 )
- {
- G_Printf( "admin_log: error could not open %s\n", g_adminLog.string );
- return ;
- }
+ if( adminLog[ 0 ] )
+ G_LogPrintf( "AdminExec: %s: %s\n", ok ? "ok" : "fail", adminLog );
+ admin_log_abort( );
+}
- sec = (level.time - level.startTime) / 1000;
- min = sec / 60;
- sec -= min * 60;
- tens = sec / 10;
- sec -= tens * 10;
+struct llist
+{
+ struct llist *next;
+};
+static int admin_search( gentity_t *ent,
+ const char *cmd,
+ const char *noun,
+ qboolean ( *match )( void *, const void * ),
+ void ( *out )( void *, char * ),
+ const void *list,
+ const void *arg, /* this will be used as char* later */
+ int start,
+ const int offset,
+ const int limit )
+{
+ int i;
+ int count = 0;
+ int found = 0;
+ int total;
+ int next = 0, end = 0;
+ char str[ MAX_STRING_CHARS ];
+ struct llist *l = (struct llist *)list;
+
+ for( total = 0; l; total++, l = l->next ) ;
+ if( start < 0 )
+ start += total;
+ else
+ start -= offset;
+ if( start < 0 || start > total )
+ start = 0;
- *flags = '\0';
- if( admin )
+ ADMBP_begin();
+ for( i = 0, l = (struct llist *)list; l; i++, l = l->next )
{
- for( i = 0; i < MAX_ADMIN_ADMINS && g_admin_admins[ i ]; i++ )
+ if( match( l, arg ) )
{
- if( !Q_stricmp( g_admin_admins[ i ]->guid , admin->client->pers.guid ) )
+ if( i >= start && ( limit < 1 || count < limit ) )
{
-
- a = g_admin_admins[ i ];
- Q_strncpyz( flags, a->flags, sizeof( flags ) );
- for( j = 0; j < MAX_ADMIN_LEVELS && g_admin_levels[ j ]; j++ )
- {
- if( g_admin_levels[ j ]->level == a->level )
- {
- l = g_admin_levels[ j ];
- Q_strcat( flags, sizeof( flags ), l->flags );
- break;
- }
- }
- break;
+ out( l, str );
+ ADMBP( va( "%-3d %s\n", i + offset, str ) );
+ count++;
+ end = i;
+ }
+ else if( count == limit )
+ {
+ if( next == 0 )
+ next = i;
}
- }
- }
- if( G_SayArgc() > 1 + skiparg )
- {
- G_SayArgv( 1 + skiparg, name, sizeof( name ) );
- if( G_ClientNumbersFromString( name, pids ) == 1 )
- {
- victim = &g_entities[ pids[ 0 ] ];
+ found++;
}
}
- if( victim && Q_stricmp( cmd, "attempted" ) )
- {
- Com_sprintf( string, sizeof( string ),
- "%3i:%i%i: %i: %s: %s (%s): %s: %s: %s: %s: \"%s\"\n",
- min,
- tens,
- sec,
- ( admin ) ? admin->s.clientNum : -1,
- ( admin ) ? admin->client->pers.guid
- : "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
- ( admin ) ? admin->client->pers.netname : "console",
- ( admin ) ? admin->client->pers.adminName : "console",
- flags,
- cmd,
- victim->client->pers.guid,
- victim->client->pers.netname,
- G_SayConcatArgs( 2 + skiparg ) );
- }
- else
+ if( limit > 0 )
{
- Com_sprintf( string, sizeof( string ),
- "%3i:%i%i: %i: %s: %s (%s): %s: %s: \"%s\"\n",
- min,
- tens,
- sec,
- ( admin ) ? admin->s.clientNum : -1,
- ( admin ) ? admin->client->pers.guid
- : "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
- ( admin ) ? admin->client->pers.netname : "console",
- ( admin ) ? admin->client->pers.adminName : "console",
- flags,
- cmd,
- G_SayConcatArgs( 1 + skiparg ) );
+ ADMBP( va( "^3%s: ^7showing %d of %d %s %d-%d%s%s.",
+ cmd, count, found, noun, start + offset, end + offset,
+ *(char *)arg ? " matching " : "", (char *)arg ) );
+ if( next )
+ ADMBP( va( " use '%s%s%s %d' to see more", cmd,
+ *(char *)arg ? " " : "",
+ (char *)arg,
+ next + offset ) );
}
+ ADMBP( "\n" );
+ ADMBP_end();
+ return next + offset;
+}
- if( g_decolourLogfiles.integer )
- {
- G_DecolorString( string, decoloured );
- trap_FS_Write( decoloured, strlen( decoloured ), f );
- }
- else
+static qboolean admin_match( void *admin, const void *match )
+{
+ char n1[ MAX_NAME_LENGTH ], n2[ MAX_NAME_LENGTH ];
+ G_SanitiseString( (char *)match, n2, sizeof( n2 ) );
+ if( !n2[ 0 ] )
+ return qtrue;
+ G_SanitiseString( ( (g_admin_admin_t *)admin )->name, n1, sizeof( n1 ) );
+ return strstr( n1, n2 ) ? qtrue : qfalse;
+}
+static void admin_out( void *admin, char *str )
+{
+ g_admin_admin_t *a = (g_admin_admin_t *)admin;
+ g_admin_level_t *l = G_admin_level( a->level );
+ int lncol = 0, i;
+ for( i = 0; l && l->name[ i ]; i++ )
{
- trap_FS_Write( string, strlen( string ), f );
+ if( Q_IsColorString( l->name + i ) )
+ lncol += 2;
}
- trap_FS_FCloseFile( f );
-
- if ( !Q_stricmp( cmd, "attempted" ) )
- {
- Com_sprintf( string, sizeof( string ),
- "%s^7 (%i) %s: %s",
- ( admin ) ? admin->client->pers.netname : "console",
- ( admin ) ? admin->s.clientNum : -1,
- cmd,
- G_SayConcatArgs( 1 + skiparg ) );
- G_AdminsPrintf("%s\n",string);
- }
-
- G_LogPrintf("Admin Command: %s^7 (%s): %s %s\n",( admin ) ? admin->client->pers.netname : "console", ( admin ) ? admin->client->pers.adminName : "console", cmd, G_SayConcatArgs( 1 + skiparg ));
+ Com_sprintf( str, MAX_STRING_CHARS, "%-6d %*s^7 %s",
+ a->level, admin_level_maxname + lncol - 1, l ? l->name : "(null)",
+ a->name );
}
-
-static int admin_listadmins( gentity_t *ent, int start, char *search, int minlevel )
+static int admin_listadmins( gentity_t *ent, int start, char *search )
{
- int drawn = 0;
- char guid_stub[9];
- char name[ MAX_NAME_LENGTH ] = {""};
- char name2[ MAX_NAME_LENGTH ] = {""};
- char lname[ MAX_NAME_LENGTH ] = {""};
- char lname_fmt[ 5 ];
- int i,j;
- gentity_t *vic;
- int l = 0;
- qboolean dup = qfalse;
-
- ADMBP_begin();
-
- // print out all connected players regardless of level if name searching
- for( i = 0; i < level.maxclients && search[ 0 ]; i++ )
- {
- vic = &g_entities[ i ];
-
- if( vic->client && vic->client->pers.connected != CON_CONNECTED )
- continue;
-
- l = vic->client->pers.adminLevel;
-
- G_SanitiseString( vic->client->pers.netname, name, sizeof( name ) );
- if( !strstr( name, search ) )
- continue;
-
- for( j = 0; j < 8; j++ )
- guid_stub[ j ] = vic->client->pers.guid[ j + 24 ];
- guid_stub[ j ] = '\0';
-
- lname[ 0 ] = '\0';
- Q_strncpyz( lname_fmt, "%s", sizeof( lname_fmt ) );
- for( j = 0; j < MAX_ADMIN_LEVELS && g_admin_levels[ j ]; j++ )
- {
- if( g_admin_levels[ j ]->level == l )
- {
- G_DecolorString( g_admin_levels[ j ]->name, lname );
- Com_sprintf( lname_fmt, sizeof( lname_fmt ), "%%%is",
- ( admin_level_maxname + strlen( g_admin_levels[ j ]->name )
- - strlen( lname ) ) );
- Com_sprintf( lname, sizeof( lname ), lname_fmt,
- g_admin_levels[ j ]->name );
- break;
- }
- }
- ADMBP( va( "%4i %4i %s^7 (*%s) %s^7\n",
- i,
- l,
- lname,
- guid_stub,
- vic->client->pers.netname ) );
- drawn++;
- }
-
- for( i = 0; i < MAX_ADMIN_ADMINS && g_admin_admins[ i ]
- && drawn < MAX_ADMIN_LISTITEMS; i++ )
- if( g_admin_admins[ i ]->level >= minlevel )
- {
-
- if( start )
- {
- start--;
- continue;
- }
-
- if( search[ 0 ] )
- {
- G_SanitiseString( g_admin_admins[ i ]->name, name, sizeof( name ) );
- if( !strstr( name, search ) )
- continue;
-
- // verify we don't have the same guid/name pair in connected players
- // since we don't want to draw the same player twice
- dup = qfalse;
- for( j = 0; j < level.maxclients; j++ )
- {
- vic = &g_entities[ j ];
- if( !vic->client || vic->client->pers.connected != CON_CONNECTED )
- continue;
- G_SanitiseString( vic->client->pers.netname, name2, sizeof( name2) );
- if( !Q_stricmp( vic->client->pers.guid, g_admin_admins[ i ]->guid )
- && strstr( name2, search ) )
- {
- dup = qtrue;
- break;
- }
- }
- if( dup )
- continue;
- }
- for( j = 0; j < 8; j++ )
- guid_stub[ j ] = g_admin_admins[ i ]->guid[ j + 24 ];
- guid_stub[ j ] = '\0';
-
- lname[ 0 ] = '\0';
- Q_strncpyz( lname_fmt, "%s", sizeof( lname_fmt ) );
- for( j = 0; j < MAX_ADMIN_LEVELS && g_admin_levels[ j ]; j++ )
- {
- if( g_admin_levels[ j ]->level == g_admin_admins[ i ]->level )
- {
- G_DecolorString( g_admin_levels[ j ]->name, lname );
- Com_sprintf( lname_fmt, sizeof( lname_fmt ), "%%%is",
- ( admin_level_maxname + strlen( g_admin_levels[ j ]->name )
- - strlen( lname ) ) );
- Com_sprintf( lname, sizeof( lname ), lname_fmt,
- g_admin_levels[ j ]->name );
- break;
- }
- }
- ADMBP( va( "%4i %4i %s^7 (*%s) %s^7\n",
- ( i + MAX_CLIENTS ),
- g_admin_admins[ i ]->level,
- lname,
- guid_stub,
- g_admin_admins[ i ]->name ) );
- drawn++;
- }
- ADMBP_end();
- return drawn;
+ return admin_search( ent, "listadmins", "admins", admin_match, admin_out,
+ g_admin_admins, search, start, MAX_CLIENTS, MAX_ADMIN_LISTITEMS );
}
+#define MAX_DURATION_LENGTH 13
void G_admin_duration( int secs, char *duration, int dursize )
{
-
+ // sizeof("12.5 minutes") == 13
if( secs > ( 60 * 60 * 24 * 365 * 50 ) || secs < 0 )
Q_strncpyz( duration, "PERMANENT", dursize );
else if( secs >= ( 60 * 60 * 24 * 365 ) )
@@ -1278,440 +880,200 @@ void G_admin_duration( int secs, char *duration, int dursize )
Com_sprintf( duration, dursize, "%i seconds", secs );
}
-qboolean G_admin_ban_check( char *userinfo, char *reason, int rlen )
+static void G_admin_ban_message(
+ gentity_t *ent,
+ g_admin_ban_t *ban,
+ char *creason,
+ int clen,
+ char *areason,
+ int alen )
+{
+ if( creason )
+ {
+ char duration[ MAX_DURATION_LENGTH ];
+ G_admin_duration( ban->expires - trap_RealTime( NULL ), duration,
+ sizeof( duration ) );
+ // part of this might get cut off on the connect screen
+ Com_sprintf( creason, clen,
+ "You have been banned by %s" S_COLOR_WHITE " duration: %s"
+ " reason: %s",
+ ban->banner,
+ duration,
+ ban->reason );
+ }
+
+ if( areason && ent )
+ {
+ // we just want the ban number
+ int n = 1;
+ g_admin_ban_t *b = g_admin_bans;
+ for( ; b && b != ban; b = b->next, n++ )
+ ;
+ Com_sprintf( areason, alen,
+ S_COLOR_YELLOW "Banned player %s" S_COLOR_YELLOW
+ " tried to connect from %s (ban #%d)",
+ ent->client->pers.netname[ 0 ] ? ent->client->pers.netname : ban->name,
+ ent->client->pers.ip.str,
+ n );
+ }
+}
+
+static qboolean G_admin_ban_matches( g_admin_ban_t *ban, gentity_t *ent )
+{
+ return !Q_stricmp( ban->guid, ent->client->pers.guid ) ||
+ ( !G_admin_permission( ent, ADMF_IMMUNITY ) &&
+ G_AddressCompare( &ban->ip, &ent->client->pers.ip ) );
+}
+
+static g_admin_ban_t *G_admin_match_ban( gentity_t *ent )
{
- static char lastConnectIP[ 16 ] = {""};
- static int lastConnectTime = 0;
- char guid[ 33 ];
- char ip[ 16 ];
- char *value;
- int i;
- unsigned int userIP = 0, intIP = 0, tempIP;
- int IP[5], k, mask, ipscanfcount;
int t;
- char notice[51];
- qboolean ignoreIP = qfalse;
-
- trap_Cvar_VariableStringBuffer( "g_banNotice", notice, sizeof( notice ) );
-
- *reason = '\0';
-
- if( !*userinfo )
- return qfalse;
-
- value = Info_ValueForKey( userinfo, "ip" );
- Q_strncpyz( ip, value, sizeof( ip ) );
- // strip port
- value = strchr( ip, ':' );
- if ( value )
- *value = '\0';
-
- if( !*ip )
- return qfalse;
-
- value = Info_ValueForKey( userinfo, "cl_guid" );
- Q_strncpyz( guid, value, sizeof( guid ) );
-
+ g_admin_ban_t *ban;
+
t = trap_RealTime( NULL );
- memset( IP, 0, sizeof( IP ));
- sscanf(ip, "%i.%i.%i.%i", &IP[4], &IP[3], &IP[2], &IP[1]);
- for(k = 4; k >= 1; k--)
- {
- if(!IP[k]) continue;
- userIP |= IP[k] << 8*(k-1);
- }
- ignoreIP = G_admin_permission_guid( guid , ADMF_BAN_IMMUNITY );
- for( i = 0; i < MAX_ADMIN_BANS && g_admin_bans[ i ]; i++ )
+ if( ent->client->pers.localClient )
+ return NULL;
+
+ for( ban = g_admin_bans; ban; ban = ban->next )
{
// 0 is for perm ban
- if( g_admin_bans[ i ]->expires != 0 &&
- ( g_admin_bans[ i ]->expires - t ) < 1 )
- continue;
- //if suspend time is over continue
- if( g_admin_bans[ i ]->suspend >= t )
+ if( ban->expires != 0 && ban->expires <= t )
continue;
- if( !ignoreIP )
- {
- tempIP = userIP;
- intIP = 0;
- mask = -1;
-
- memset( IP, 0, sizeof( IP ));
- ipscanfcount = sscanf(g_admin_bans[ i ]->ip, "%d.%d.%d.%d/%d", &IP[4], &IP[3], &IP[2], &IP[1], &IP[0]);
-
- if( ipscanfcount == 4 )
- mask = -1;
- else if( ipscanfcount == 5 )
- mask = IP[0];
- else if( ipscanfcount > 0 && ipscanfcount < 4 )
- mask = 8 * ipscanfcount;
- else
- continue;
+ if( G_admin_ban_matches( ban, ent ) )
+ return ban;
+ }
- for(k = 4; k >= 1; k--)
- {
- if(!IP[k]) continue;
- intIP |= IP[k] << 8*(k-1);
- }
+ return NULL;
+}
- if(mask > 0 && mask <= 32)
- {
- tempIP &= ~((1 << (32-mask)) - 1);
- intIP &= ~((1 << (32-mask)) - 1);
- }
+qboolean G_admin_ban_check( gentity_t *ent, char *reason, int rlen )
+{
+ g_admin_ban_t *ban;
+ char warningMessage[ MAX_STRING_CHARS ];
- if( intIP == tempIP || mask == 0 )
- {
- char duration[ 32 ];
- G_admin_duration( ( g_admin_bans[ i ]->expires - t ),
- duration, sizeof( duration ) );
-
- // flood protected
- if( t - lastConnectTime >= 300 ||
- Q_stricmp( lastConnectIP, ip ) )
- {
- lastConnectTime = t;
- Q_strncpyz( lastConnectIP, ip, sizeof( lastConnectIP ) );
-
- G_WarningsPrintf(
- "ban",
- "Banned player %s^7 (%s^7) tried to connect (ban #%i on %s by %s^7 expires %s reason: %s^7 )\n",
- Info_ValueForKey( userinfo, "name" ),
- g_admin_bans[ i ]->name,
- i+1,
- ip,
- g_admin_bans[ i ]->banner,
- duration,
- g_admin_bans[ i ]->reason );
- }
-
- Com_sprintf(
- reason,
- rlen,
- "You have been banned by %s^7 reason: %s^7 expires: %s %s",
- g_admin_bans[ i ]->banner,
- g_admin_bans[ i ]->reason,
- duration,
- notice
- );
- G_LogPrintf("Banned player tried to connect from IP %s\n", ip);
- return qtrue;
- }
- }
- if( *guid && !Q_stricmp( g_admin_bans[ i ]->guid, guid ) )
- {
- char duration[ 32 ];
- G_admin_duration( ( g_admin_bans[ i ]->expires - t ),
- duration, sizeof( duration ) );
- Com_sprintf(
- reason,
- rlen,
- "You have been banned by %s^7 reason: %s^7 expires: %s",
- g_admin_bans[ i ]->banner,
- g_admin_bans[ i ]->reason,
- duration
- );
- G_Printf("Banned player tried to connect with GUID %s\n", guid);
- return qtrue;
- }
- }
- if ( *guid )
+ if( ent->client->pers.localClient )
+ return qfalse;
+
+ if( ( ban = G_admin_match_ban( ent ) ) )
{
- int count = 0;
- qboolean valid = qtrue;
+ G_admin_ban_message( ent, ban, reason, rlen,
+ warningMessage, sizeof( warningMessage ) );
- while( guid[ count ] != '\0' && valid )
- {
- if( (guid[ count ] < '0' || guid[ count ] > '9') &&
- (guid[ count ] < 'A' || guid[ count ] > 'F') )
- {
- valid = qfalse;
- }
- count++;
- }
- if( !valid || count != 32 )
- {
- Com_sprintf( reason, rlen, "Invalid client data" );
- G_Printf("Player with invalid GUID [%s] connect from IP %s\n", guid, ip);
- return qtrue;
- }
+ // don't spam admins
+ if( ban->warnCount++ < 5 )
+ G_AdminMessage( NULL, warningMessage );
+ // and don't fill the console
+ else if( ban->warnCount < 10 )
+ trap_Print( va( "%s%s\n", warningMessage,
+ ban->warnCount + 1 == 10 ?
+ S_COLOR_WHITE " - future messages for this ban will be suppressed" :
+ "" ) );
+ return qtrue;
}
+
return qfalse;
}
-qboolean G_admin_cmd_check( gentity_t *ent, qboolean say )
+qboolean G_admin_cmd_check( gentity_t *ent )
{
- int i;
char command[ MAX_ADMIN_CMD_LEN ];
- char *cmd;
- int skip = 0;
+ g_admin_cmd_t *admincmd;
+ g_admin_command_t *c;
+ qboolean success;
command[ 0 ] = '\0';
- G_SayArgv( 0, command, sizeof( command ) );
- if( !Q_stricmp( command, "say" ) ||
- ( G_admin_permission( ent, ADMF_TEAMCHAT_CMD ) &&
- ( !Q_stricmp( command, "say_team" ) ) ) )
- {
- skip = 1;
- G_SayArgv( 1, command, sizeof( command ) );
- }
+ trap_Argv( 0, command, sizeof( command ) );
if( !command[ 0 ] )
return qfalse;
- if( command[ 0 ] == '!' )
- {
- cmd = &command[ 1 ];
- }
- else
- {
- return qfalse;
- }
-
- // Flood limit. If they're talking too fast, determine that and return.
- if( g_floodMinTime.integer )
- if ( G_Flood_Limited( ent ) )
- {
- trap_SendServerCommand( ent-g_entities, "print \"Your chat is flood-limited; wait before chatting again\n\"" );
- return qtrue;
- }
+ Q_strlwr( command );
+ admin_log_start( ent, command );
- if( G_admin_is_restricted( ent, qtrue ) )
- return qtrue;
-
- for( i = 0; i < MAX_ADMIN_COMMANDS && g_admin_commands[ i ]; i++ )
+ if( ( c = G_admin_command( command ) ) )
{
- if( Q_stricmp( cmd, g_admin_commands[ i ]->command ) )
- continue;
-
- if( G_admin_permission( ent, g_admin_commands[ i ]->flag ) )
+ admin_log( ConcatArgsPrintable( 1 ) );
+ if( ( success = G_admin_permission( ent, c->flag ) ) )
{
- trap_SendConsoleCommand( EXEC_APPEND, g_admin_commands[ i ]->exec );
- admin_log( ent, cmd, skip );
- G_admin_adminlog_log( ent, cmd, NULL, skip, qtrue );
+ if( G_FloodLimited( ent ) )
+ return qtrue;
+ trap_SendConsoleCommand( EXEC_APPEND, c->exec );
}
else
{
- ADMP( va( "^3!%s: ^7permission denied\n", g_admin_commands[ i ]->command ) );
- admin_log( ent, "attempted", skip - 1 );
- G_admin_adminlog_log( ent, cmd, NULL, skip, qfalse );
+ ADMP( va( "^3%s: ^7permission denied\n", c->command ) );
}
+ admin_log_end( success );
return qtrue;
}
- for( i = 0; i < adminNumCmds; i++ )
+ if( ( admincmd = G_admin_cmd( command ) ) )
{
- if( Q_stricmp( cmd, g_admin_cmds[ i ].keyword ) )
- continue;
-
- if( G_admin_permission( ent, g_admin_cmds[ i ].flag ) )
+ if( ( success = G_admin_permission( ent, admincmd->flag ) ) )
{
- g_admin_cmds[ i ].handler( ent, skip );
- admin_log( ent, cmd, skip );
- G_admin_adminlog_log( ent, cmd, NULL, skip, qtrue );
+ if( G_FloodLimited( ent ) )
+ return qtrue;
+ if( admincmd->silent )
+ admin_log_abort( );
+ if( !( success = admincmd->handler( ent ) ) )
+ admin_log( ConcatArgsPrintable( 1 ) );
}
else
{
- ADMP( va( "^3!%s: ^7permission denied\n", g_admin_cmds[ i ].keyword ) );
- admin_log( ent, "attempted", skip - 1 );
- G_admin_adminlog_log( ent, cmd, NULL, skip, qfalse );
+ ADMP( va( "^3%s: ^7permission denied\n", admincmd->keyword ) );
+ admin_log( ConcatArgsPrintable( 1 ) );
}
+ admin_log_end( success );
return qtrue;
}
return qfalse;
}
-void G_admin_namelog_cleanup( )
+static void llsort( struct llist **head, int compar( const void *, const void * ) )
{
- int i;
+ struct llist *a, *b, *t, *l;
+ int i, c = 1, ns, as, bs;
- for( i = 0; i < MAX_ADMIN_NAMELOGS && g_admin_namelog[ i ]; i++ )
- {
- if( g_admin_namelog[ i ]->smj.comment )
- G_Free( g_admin_namelog[ i ]->smj.comment );
- G_Free( g_admin_namelog[ i ] );
- g_admin_namelog[ i ] = NULL;
- }
-}
-
-static void dispatchSchachtmeisterIPAQuery( const char *ipa )
-{
- trap_SendConsoleCommand( EXEC_APPEND, va( "smq ipa \"%s\"\n", ipa ) );
-}
-
-static void schachtmeisterProcess( g_admin_namelog_t *namelog )
-{
- schachtmeisterJudgement_t *j = &namelog->smj;
-
- if( !j->ratingTime || level.time - j->ratingTime >= 600000 )
- {
- if( j->queryTime )
- return;
-
- j->queryTime = level.time;
- goto dispatch;
- }
-
- if( !j->queryTime || level.time - j->queryTime >= 60000 )
- return;
-
- if( j->dispatchTime && level.time - j->dispatchTime < 5000 )
+ if( !*head )
return;
- dispatch:
- j->dispatchTime = level.time;
- dispatchSchachtmeisterIPAQuery( namelog->ip );
-}
-
-void G_admin_schachtmeisterFrame( void )
-{
- int i;
- for( i = 0; i < MAX_ADMIN_NAMELOGS && g_admin_namelog[ i ]; i++ )
- schachtmeisterProcess( g_admin_namelog[ i ] );
-}
-
-void G_admin_namelog_update( gclient_t *client, qboolean disconnect )
-{
- int i, j;
- g_admin_namelog_t *namelog;
- char n1[ MAX_NAME_LENGTH ];
- char n2[ MAX_NAME_LENGTH ];
- int clientNum = ( client - level.clients );
-
- if ( client->sess.invisible == qfalse )
- {
- G_admin_seen_update( client->pers.guid );
- }
-
- G_SanitiseString( client->pers.netname, n1, sizeof( n1 ) );
- for( i = 0; i < MAX_ADMIN_NAMELOGS && g_admin_namelog[ i ]; i++ )
+ do
{
- if( disconnect && g_admin_namelog[ i ]->slot != clientNum )
- continue;
-
- if( !disconnect && !( g_admin_namelog[ i ]->slot == clientNum ||
- g_admin_namelog[ i ]->slot == -1 ) )
+ a = *head, l = *head = NULL;
+ for( ns = 0; a; ns++, a = b )
{
- continue;
- }
-
- if( !Q_stricmp( client->pers.ip, g_admin_namelog[ i ]->ip )
- && !Q_stricmp( client->pers.guid, g_admin_namelog[ i ]->guid ) )
- {
- for( j = 0; j < MAX_ADMIN_NAMELOG_NAMES
- && g_admin_namelog[ i ]->name[ j ][ 0 ]; j++ )
+ b = a;
+ for( i = as = 0; i < c; i++ )
{
- G_SanitiseString( g_admin_namelog[ i ]->name[ j ], n2, sizeof( n2 ) );
- if( !Q_stricmp( n1, n2 ) )
+ as++;
+ if( !( b = b->next ) )
break;
}
- if( j == MAX_ADMIN_NAMELOG_NAMES )
- j = MAX_ADMIN_NAMELOG_NAMES - 1;
- Q_strncpyz( g_admin_namelog[ i ]->name[ j ], client->pers.netname,
- sizeof( g_admin_namelog[ i ]->name[ j ] ) );
- g_admin_namelog[ i ]->slot = ( disconnect ) ? -1 : clientNum;
-
- // if this player is connecting, they are no longer banned
- if( !disconnect )
- g_admin_namelog[ i ]->banned = qfalse;
-
- //check other things like if user was denybuild or muted or denyweapon and restore them
- if( !disconnect )
- {
- if( g_admin_namelog[ i ]->muted )
- {
- client->pers.muted = qtrue;
- client->pers.muteExpires = g_admin_namelog[ i ]->muteExpires;
- G_AdminsPrintf( "^7%s^7's mute has been restored\n", client->pers.netname );
- g_admin_namelog[ i ]->muted = qfalse;
- }
- if( g_admin_namelog[ i ]->denyBuild )
- {
- client->pers.denyBuild = qtrue;
- G_AdminsPrintf( "^7%s^7's Denybuild has been restored\n", client->pers.netname );
- g_admin_namelog[ i ]->denyBuild = qfalse;
- }
- if( g_admin_namelog[ i ]->denyHumanWeapons > 0 || g_admin_namelog[ i ]->denyAlienClasses > 0 )
- {
- if( g_admin_namelog[ i ]->denyHumanWeapons > 0 )
- client->pers.denyHumanWeapons = g_admin_namelog[ i ]->denyHumanWeapons;
- if( g_admin_namelog[ i ]->denyAlienClasses > 0 )
- client->pers.denyAlienClasses = g_admin_namelog[ i ]->denyAlienClasses;
-
- G_AdminsPrintf( "^7%s^7's Denyweapon has been restored\n", client->pers.netname );
- g_admin_namelog[ i ]->denyHumanWeapons = 0;
- g_admin_namelog[ i ]->denyAlienClasses = 0;
- }
- if( g_admin_namelog[ i ]->specExpires > 0 )
- {
- client->pers.specExpires = g_admin_namelog[ i ]->specExpires;
- G_AdminsPrintf( "^7%s^7's Putteam spectator has been restored\n", client->pers.netname );
- g_admin_namelog[ i ]->specExpires = 0;
- }
- if( g_admin_namelog[ i ]->voteCount > 0 )
- {
- client->pers.voteCount = g_admin_namelog[ i ]->voteCount;
- g_admin_namelog[ i ]->voteCount = 0;
- }
- }
- else
+ for( bs = c; ( b && bs ) || as; l = t )
{
- //for mute
- if( G_IsMuted( client ) )
- {
- g_admin_namelog[ i ]->muted = qtrue;
- g_admin_namelog[ i ]->muteExpires = client->pers.muteExpires;
- }
- //denybuild
- if( client->pers.denyBuild )
- {
- g_admin_namelog[ i ]->denyBuild = qtrue;
- }
- //denyweapon humans
- if( client->pers.denyHumanWeapons > 0 )
- {
- g_admin_namelog[ i ]->denyHumanWeapons = client->pers.denyHumanWeapons;
- }
- //denyweapon aliens
- if( client->pers.denyAlienClasses > 0 )
- {
- g_admin_namelog[ i ]->denyAlienClasses = client->pers.denyAlienClasses;
- }
- //putteam spec
- if( client->pers.specExpires > 0 )
- {
- g_admin_namelog[ i ]->specExpires = client->pers.specExpires;
- }
- if( client->pers.voteCount > 0 )
- {
- g_admin_namelog[ i ]->voteCount = client->pers.voteCount;
- }
+ if( as && ( !bs || !b || compar( a, b ) <= 0 ) )
+ t = a, a = a->next, as--;
+ else
+ t = b, b = b->next, bs--;
+ if( l )
+ l->next = t;
+ else
+ *head = t;
}
-
- return;
}
- }
- if( i >= MAX_ADMIN_NAMELOGS )
- {
- G_Printf( "G_admin_namelog_update: warning, g_admin_namelogs overflow\n" );
- return;
- }
- namelog = G_Alloc( sizeof( g_admin_namelog_t ) );
- memset( namelog, 0, sizeof( *namelog ) );
- for( j = 0; j < MAX_ADMIN_NAMELOG_NAMES ; j++ )
- namelog->name[ j ][ 0 ] = '\0';
- Q_strncpyz( namelog->ip, client->pers.ip, sizeof( namelog->ip ) );
- Q_strncpyz( namelog->guid, client->pers.guid, sizeof( namelog->guid ) );
- Q_strncpyz( namelog->name[ 0 ], client->pers.netname,
- sizeof( namelog->name[ 0 ] ) );
- namelog->slot = ( disconnect ) ? -1 : clientNum;
- schachtmeisterProcess( namelog );
- g_admin_namelog[ i ] = namelog;
+ l->next = NULL;
+ c *= 2;
+ } while( ns > 1 );
+}
+
+static int cmplevel( const void *a, const void *b )
+{
+ return ((g_admin_level_t *)b)->level - ((g_admin_level_t *)a)->level;
}
-qboolean G_admin_readconfig( gentity_t *ent, int skiparg )
+qboolean G_admin_readconfig( gentity_t *ent )
{
- g_admin_level_t * l = NULL;
+ g_admin_level_t *l = NULL;
g_admin_admin_t *a = NULL;
g_admin_ban_t *b = NULL;
g_admin_command_t *c = NULL;
@@ -1722,54 +1084,82 @@ qboolean G_admin_readconfig( gentity_t *ent, int skiparg )
char *t;
qboolean level_open, admin_open, ban_open, command_open;
int i;
+ char ip[ 44 ];
G_admin_cleanup();
if( !g_admin.string[ 0 ] )
{
- ADMP( "^3!readconfig: g_admin is not set, not loading configuration "
+ ADMP( "^3readconfig: g_admin is not set, not loading configuration "
"from a file\n" );
- admin_default_levels();
return qfalse;
}
- len = trap_FS_FOpenFile( g_admin.string, &f, FS_READ ) ;
+ 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 ) );
+ G_Printf( "^3readconfig: ^7could not open admin config file %s\n",
+ g_admin.string );
admin_default_levels();
return qfalse;
}
- cnf = G_Alloc( len + 1 );
+ cnf = BG_Alloc( len + 1 );
cnf2 = cnf;
trap_FS_Read( cnf, len, f );
*( cnf + len ) = '\0';
trap_FS_FCloseFile( f );
- t = COM_Parse( &cnf );
+ admin_level_maxname = 0;
+
level_open = admin_open = ban_open = command_open = qfalse;
- while( *t )
+ COM_BeginParseSession( g_admin.string );
+ while( 1 )
{
- if( !Q_stricmp( t, "[level]" ) ||
- !Q_stricmp( t, "[admin]" ) ||
- !Q_stricmp( t, "[ban]" ) ||
- !Q_stricmp( t, "[command]" ) )
- {
+ t = COM_Parse( &cnf );
+ if( !*t )
+ break;
- if( level_open )
- g_admin_levels[ lc++ ] = l;
- else if( admin_open )
- g_admin_admins[ ac++ ] = a;
- 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;
+ if( !Q_stricmp( t, "[level]" ) )
+ {
+ if( l )
+ l = l->next = BG_Alloc( sizeof( g_admin_level_t ) );
+ else
+ l = g_admin_levels = BG_Alloc( sizeof( g_admin_level_t ) );
+ level_open = qtrue;
+ admin_open = ban_open = command_open = qfalse;
+ lc++;
}
-
- if( level_open )
+ else if( !Q_stricmp( t, "[admin]" ) )
+ {
+ if( a )
+ a = a->next = BG_Alloc( sizeof( g_admin_admin_t ) );
+ else
+ a = g_admin_admins = BG_Alloc( sizeof( g_admin_admin_t ) );
+ admin_open = qtrue;
+ level_open = ban_open = command_open = qfalse;
+ ac++;
+ }
+ else if( !Q_stricmp( t, "[ban]" ) )
+ {
+ if( b )
+ b = b->next = BG_Alloc( sizeof( g_admin_ban_t ) );
+ else
+ b = g_admin_bans = BG_Alloc( sizeof( g_admin_ban_t ) );
+ ban_open = qtrue;
+ level_open = admin_open = command_open = qfalse;
+ bc++;
+ }
+ else if( !Q_stricmp( t, "[command]" ) )
+ {
+ if( c )
+ c = c->next = BG_Alloc( sizeof( g_admin_command_t ) );
+ else
+ c = g_admin_commands = BG_Alloc( sizeof( g_admin_command_t ) );
+ command_open = qtrue;
+ level_open = admin_open = ban_open = qfalse;
+ cc++;
+ }
+ else if( level_open )
{
if( !Q_stricmp( t, "level" ) )
{
@@ -1778,6 +1168,10 @@ qboolean G_admin_readconfig( gentity_t *ent, int skiparg )
else if( !Q_stricmp( t, "name" ) )
{
admin_readconfig_string( &cnf, l->name, sizeof( l->name ) );
+ // max printable name length for formatting
+ len = Q_PrintStrlen( l->name );
+ if( len > admin_level_maxname )
+ admin_level_maxname = len;
}
else if( !Q_stricmp( t, "flags" ) )
{
@@ -1785,9 +1179,7 @@ qboolean G_admin_readconfig( gentity_t *ent, int skiparg )
}
else
{
- ADMP( va( "^3!readconfig: ^7[level] parse error near %s on line %d\n",
- t,
- COM_GetCurrentParseLine() ) );
+ COM_ParseError( "[level] unrecognized token \"%s\"", t );
}
}
else if( admin_open )
@@ -1808,15 +1200,9 @@ qboolean G_admin_readconfig( gentity_t *ent, int skiparg )
{
admin_readconfig_string( &cnf, a->flags, sizeof( a->flags ) );
}
- else if( !Q_stricmp( t, "seen" ) )
- {
- admin_readconfig_int( &cnf, &a->seen );
- }
else
{
- ADMP( va( "^3!readconfig: ^7[admin] parse error near %s on line %d\n",
- t,
- COM_GetCurrentParseLine() ) );
+ COM_ParseError( "[admin] unrecognized token \"%s\"", t );
}
}
@@ -1832,7 +1218,8 @@ qboolean G_admin_readconfig( gentity_t *ent, int skiparg )
}
else if( !Q_stricmp( t, "ip" ) )
{
- admin_readconfig_string( &cnf, b->ip, sizeof( b->ip ) );
+ admin_readconfig_string( &cnf, ip, sizeof( ip ) );
+ G_AddressParse( ip, &b->ip );
}
else if( !Q_stricmp( t, "reason" ) )
{
@@ -1846,23 +1233,13 @@ qboolean G_admin_readconfig( gentity_t *ent, int skiparg )
{
admin_readconfig_int( &cnf, &b->expires );
}
- else if( !Q_stricmp( t, "suspend" ) )
- {
- admin_readconfig_int( &cnf, &b->suspend );
- }
else if( !Q_stricmp( t, "banner" ) )
{
admin_readconfig_string( &cnf, b->banner, sizeof( b->banner ) );
}
- else if( !Q_stricmp( t, "blevel" ) )
- {
- admin_readconfig_int( &cnf, &b->bannerlevel );
- }
else
{
- ADMP( va( "^3!readconfig: ^7[ban] parse error near %s on line %d\n",
- t,
- COM_GetCurrentParseLine() ) );
+ COM_ParseError( "[ban] unrecognized token \"%s\"", t );
}
}
else if( command_open )
@@ -1885,761 +1262,305 @@ qboolean G_admin_readconfig( gentity_t *ent, int skiparg )
}
else
{
- ADMP( va( "^3!readconfig: ^7[command] parse error near %s on line %d\n",
- t,
- COM_GetCurrentParseLine() ) );
+ COM_ParseError( "[command] unrecognized token \"%s\"", t );
}
}
-
- if( !Q_stricmp( t, "[level]" ) )
- {
- if( lc >= MAX_ADMIN_LEVELS )
- return qfalse;
- l = G_Alloc( sizeof( g_admin_level_t ) );
- l->level = 0;
- *l->name = '\0';
- *l->flags = '\0';
- level_open = qtrue;
- }
- else if( !Q_stricmp( t, "[admin]" ) )
- {
- if( ac >= MAX_ADMIN_ADMINS )
- return qfalse;
- a = G_Alloc( sizeof( g_admin_admin_t ) );
- *a->name = '\0';
- *a->guid = '\0';
- a->level = 0;
- *a->flags = '\0';
- a->seen = 0;
- admin_open = qtrue;
- }
- else if( !Q_stricmp( t, "[ban]" ) )
- {
- if( bc >= MAX_ADMIN_BANS )
- return qfalse;
- b = G_Alloc( sizeof( g_admin_ban_t ) );
- *b->name = '\0';
- *b->guid = '\0';
- *b->ip = '\0';
- *b->made = '\0';
- b->expires = 0;
- b->suspend = 0;
- *b->reason = '\0';
- b->bannerlevel = 0;
- ban_open = qtrue;
- }
- else if( !Q_stricmp( t, "[command]" ) )
+ else
{
- if( cc >= MAX_ADMIN_COMMANDS )
- return qfalse;
- c = G_Alloc( sizeof( g_admin_command_t ) );
- *c->command = '\0';
- *c->exec = '\0';
- *c->desc = '\0';
- *c->flag = '\0';
- command_open = qtrue;
+ COM_ParseError( "unexpected token \"%s\"", t );
}
- t = COM_Parse( &cnf );
- }
- if( level_open )
- {
-
- g_admin_levels[ lc++ ] = l;
}
- if( admin_open )
- 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",
+ BG_Free( cnf2 );
+ ADMP( va( "^3readconfig: ^7loaded %d levels, %d admins, %d bans, %d commands\n",
lc, ac, bc, cc ) );
if( lc == 0 )
admin_default_levels();
else
{
- char n[ MAX_NAME_LENGTH ] = {""};
-
- // max printable name length for formatting
- for( i = 0; i < MAX_ADMIN_LEVELS && g_admin_levels[ i ]; i++ )
- {
- G_DecolorString( l->name, n );
- if( strlen( n ) > admin_level_maxname )
- admin_level_maxname = strlen( n );
- }
+ llsort( (struct llist **)&g_admin_levels, cmplevel );
+ llsort( (struct llist **)&g_admin_admins, cmplevel );
}
- // reset adminLevel
+
+ // restore admin mapping
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 ] );
+ {
+ level.clients[ i ].pers.admin =
+ G_admin_admin( level.clients[ i ].pers.guid );
+ if( level.clients[ i ].pers.admin )
+ G_admin_authlog( &g_entities[ i ] );
+ G_admin_cmdlist( &g_entities[ i ] );
+ }
+ }
+
return qtrue;
}
-qboolean G_admin_time( gentity_t *ent, int skiparg )
+qboolean G_admin_time( gentity_t *ent )
{
qtime_t qt;
- int t;
- t = trap_RealTime( &qt );
- ADMP( va( "^3!time: ^7local time is %02i:%02i:%02i\n",
+ trap_RealTime( &qt );
+ ADMP( va( "^3time: ^7local time is %02i:%02i:%02i\n",
qt.tm_hour, qt.tm_min, qt.tm_sec ) );
-
return qtrue;
}
-static int G_admin_find_slot( gentity_t *ent, char *namearg, const char *command )
-{
- char name[ MAX_NAME_LENGTH ];
- char testname[ MAX_NAME_LENGTH ];
- char *guid = NULL;
- int matches = 0;
- int id = -1;
- int i;
- qboolean numeric = qtrue;
-
- G_SanitiseString( namearg, name, sizeof( name ) );
- for( i = 0; i < sizeof( name ) && name[ i ] ; i++ )
- {
- if( !isdigit( name[ i ] ) )
- {
- numeric = qfalse;
- break;
- }
- }
- if( numeric )
- {
- id = atoi( name );
-
- if( id >= 0 && id < level.maxclients )
- {
- gentity_t *vic;
-
- vic = &g_entities[ id ];
- if( vic && vic->client && vic->client->pers.connected != CON_DISCONNECTED )
- return id;
-
- ADMP( va( "^3!%s:^7 no one connected by that slot number\n", command ) );
- return -1;
- }
- if( id >= MAX_CLIENTS && id < MAX_CLIENTS + MAX_ADMIN_ADMINS &&
- g_admin_admins[ id - MAX_CLIENTS ] )
- {
- return id;
- }
-
- ADMP( va( "^3!%s:^7 no match for slot or admin number %d\n", command, id ) );
- return -1;
- }
-
- for( i = 0; i < MAX_ADMIN_ADMINS && g_admin_admins[ i ] && matches < 2; i++ )
- {
- G_SanitiseString( g_admin_admins[ i ]->name, testname, sizeof( testname ) );
- if( strstr( testname, name ) )
- {
- id = i + MAX_CLIENTS;
- guid = g_admin_admins[ i ]->guid;
- matches++;
- }
- }
- for( i = 0; i < level.maxclients && matches < 2; i++ )
- {
- if( level.clients[ i ].pers.connected == CON_DISCONNECTED )
- continue;
-
- if( matches && guid && !Q_stricmp( level.clients[ i ].pers.guid, guid ) )
- continue;
-
- G_SanitiseString( level.clients[ i ].pers.netname, testname, sizeof( testname ) );
- if( strstr( testname, name ) )
- {
- id = i;
- matches++;
- }
- }
-
- if( matches == 0 )
- {
- ADMP( va( "^3!%s:^7 no match, use !listplayers or !listadmins to "
- "find an appropriate number to use instead of name.\n", command ) );
- return -1;
- }
-
- if( matches == 1 )
- return id;
-
- ADMP( va( "^3!%s:^7 multiple matches, use the admin number instead:\n", command ) );
- admin_listadmins( ent, 0, name, 0 );
+// this should be in one of the headers, but it is only used here for now
+namelog_t *G_NamelogFromString( gentity_t *ent, char *s );
- return -1;
-}
-
-static int G_admin_find_admin_slot( gentity_t *ent, char *namearg, char *command, char *nick, int nick_len )
+/*
+for consistency, we should be able to target a disconnected player with setlevel
+but we can't use namelog and remain consistent, so the solution would be to make
+everyone a real level 0 admin so they can be targeted until the next level
+but that seems kind of stupid
+*/
+qboolean G_admin_setlevel( gentity_t *ent )
{
- gentity_t *vic;
- char *guid;
- int id;
+ char name[ MAX_NAME_LENGTH ] = {""};
+ char lstr[ 12 ]; // 11 is max strlen() for 32-bit (signed) int
+ char testname[ MAX_NAME_LENGTH ] = {""};
int i;
+ gentity_t *vic = NULL;
+ g_admin_admin_t *a = NULL;
+ g_admin_level_t *l = NULL;
+ int na;
- if ( nick )
- nick[ 0 ] = '\0';
-
- id = G_admin_find_slot( ent, namearg, command );
- if( id < 0 )
- return -1;
-
- if( id < MAX_CLIENTS )
+ if( trap_Argc() < 3 )
{
- vic = &g_entities[ id ];
- guid = vic->client->pers.guid;
- for( i = 0; i < MAX_ADMIN_ADMINS && g_admin_admins[ i ]; i++ )
- {
- if( !Q_stricmp( guid, g_admin_admins[ i ]->guid ) )
- {
- id = i + MAX_CLIENTS;
- if( nick )
- Q_strncpyz( nick, vic->client->pers.netname, nick_len );
- break;
- }
- }
- if( id < MAX_CLIENTS )
- {
- ADMP( va( "^3!%s:^7 player is not !registered\n", command ) );
- return -1;
- }
+ ADMP( "^3setlevel: ^7usage: setlevel [name|slot#] [level]\n" );
+ return qfalse;
}
- id -= MAX_CLIENTS;
- if( nick && !nick[ 0 ] )
- Q_strncpyz( nick, g_admin_admins[ id ]->name, nick_len );
-
- return id;
-}
-
-qboolean G_admin_setlevel( gentity_t *ent, int skiparg )
-{
- char lstr[ 11 ]; // 10 is max strlen() for 32-bit int
- char adminname[ MAX_NAME_LENGTH ] = {""};
- char testname[ MAX_NAME_LENGTH ] = {""};
- char guid[ 33 ];
- int l, i;
- gentity_t *vic = NULL;
- qboolean updated = qfalse;
- g_admin_admin_t *a;
- qboolean found = qfalse;
- int id = -1;
+ trap_Argv( 1, testname, sizeof( testname ) );
+ trap_Argv( 2, lstr, sizeof( lstr ) );
- if( G_SayArgc() < 3 + skiparg )
+ if( !( l = G_admin_level( atoi( lstr ) ) ) )
{
- ADMP( "^3!setlevel: ^7usage: !setlevel [name|slot#] [level]\n" );
+ ADMP( "^3setlevel: ^7level is not defined\n" );
return qfalse;
}
- G_SayArgv( 1 + skiparg, testname, sizeof( testname ) );
- G_SayArgv( 2 + skiparg, lstr, sizeof( lstr ) );
- l = atoi( lstr );
- if( ent && l > ent->client->pers.adminLevel )
+ if( ent && l->level >
+ ( ent->client->pers.admin ? ent->client->pers.admin->level : 0 ) )
{
- ADMP( "^3!setlevel: ^7you may not use !setlevel to set a level higher "
+ ADMP( "^3setlevel: ^7you may not use setlevel to set a level higher "
"than your current level\n" );
return qfalse;
}
- // if admin is activated for the first time on a running server, we need
- // to ensure at least the default levels get created
- if( !ent && !g_admin_levels[ 0 ] )
- G_admin_readconfig(NULL, 0);
+ for( na = 0, a = g_admin_admins; a; na++, a = a->next );
- for( i = 0; i < MAX_ADMIN_LEVELS && g_admin_levels[ i ]; i++ )
+ for( i = 0; testname[ i ] && isdigit( testname[ i ] ); i++ );
+ if( !testname[ i ] )
{
- if( g_admin_levels[ i ]->level == l )
- {
- found = qtrue;
- break;
- }
- }
- if( !found )
- {
- ADMP( "^3!setlevel: ^7level is not defined\n" );
- return qfalse;
- }
-
- id = G_admin_find_slot( ent, testname, "setlevel" );
- if( id >=0 && id < MAX_CLIENTS )
- {
- vic = &g_entities[ id ];
- Q_strncpyz( adminname, vic->client->pers.netname, sizeof( adminname ) );
- Q_strncpyz( guid, vic->client->pers.guid, sizeof( guid ) );
- }
- else if( id >= MAX_CLIENTS && id < MAX_CLIENTS + MAX_ADMIN_ADMINS &&
- g_admin_admins[ id - MAX_CLIENTS ] )
- {
- Q_strncpyz( adminname, g_admin_admins[ id - MAX_CLIENTS ]->name,
- sizeof( adminname ) );
- Q_strncpyz( guid, g_admin_admins[ id - MAX_CLIENTS ]->guid,
- sizeof( guid ) );
- for( i = 0; i < level.maxclients; i++ )
+ int id = atoi( testname );
+ if( id < MAX_CLIENTS )
{
- if( level.clients[ i ].pers.connected == CON_DISCONNECTED )
- continue;
- if( !Q_stricmp( level.clients[ i ].pers.guid, guid ) )
+ vic = &g_entities[ id ];
+ if( !vic || !vic->client || vic->client->pers.connected == CON_DISCONNECTED )
{
- vic = &g_entities[ i ];
- Q_strncpyz( adminname, vic->client->pers.netname, sizeof( adminname ) );
+ ADMP( va( "^3setlevel: ^7no player connected in slot %d\n", id ) );
+ return qfalse;
}
}
- }
- else
- {
- return qfalse;
- }
-
- if( !Q_stricmp( guid, "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" ) )
- {
- ADMP( va( "^3!setlevel: ^7%s does not have a valid GUID\n", adminname ) );
- return qfalse;
- }
- if( ent && !admin_higher_guid( ent->client->pers.guid, guid ) )
- {
- ADMP( "^3!setlevel: ^7sorry, but your intended victim has a higher"
- " admin level than you\n" );
- return qfalse;
- }
-
- for( i = 0; i < MAX_ADMIN_ADMINS && g_admin_admins[ i ];i++ )
- {
- if( !Q_stricmp( g_admin_admins[ i ]->guid, guid ) )
- {
- g_admin_admins[ i ]->level = l;
- Q_strncpyz( g_admin_admins[ i ]->name, adminname,
- sizeof( g_admin_admins[ i ]->name ) );
- updated = qtrue;
- }
- }
- if( !updated )
- {
- if( i == MAX_ADMIN_ADMINS )
+ else if( id < na + MAX_CLIENTS )
+ for( i = 0, a = g_admin_admins; i < id - MAX_CLIENTS; i++, a = a->next );
+ else
{
- ADMP( "^3!setlevel: ^7too many admins\n" );
+ ADMP( va( "^3setlevel: ^7%s not in range 1-%d\n",
+ testname, na + MAX_CLIENTS - 1 ) );
return qfalse;
}
- a = G_Alloc( sizeof( g_admin_admin_t ) );
- a->level = l;
- Q_strncpyz( a->name, adminname, sizeof( a->name ) );
- Q_strncpyz( a->guid, guid, sizeof( a->guid ) );
- *a->flags = '\0';
- g_admin_admins[ i ] = a;
}
-
- AP( va(
- "print \"^3!setlevel: ^7%s^7 was given level %d admin rights by %s\n\"",
- adminname, l, ( ent ) ? G_admin_adminPrintName( ent ) : "console" ) );
- if( vic )
- {
- vic->client->pers.adminLevel = l;
- G_admin_set_adminname( vic );
- }
-
- if( !g_admin.string[ 0 ] )
- ADMP( "^3!setlevel: ^7WARNING g_admin not set, not saving admin record "
- "to a file\n" );
else
- admin_writeconfig();
- return qtrue;
-}
-
-static int SortFlags( const void *pa, const void *pb )
-{
- char *a = (char *)pa;
- char *b = (char *)pb;
-
- if( *a == '-' || *a == '+' )
- a++;
- if( *b == '-' || *b == '+' )
- b++;
- return strcmp(a, b);
-}
-
-#define MAX_USER_FLAGS 200
-const char *G_admin_user_flag( char *oldflags, char *flag, qboolean add, qboolean clear,
- char *newflags, int size )
-{
- char *token, *token_p;
- char *key;
- char head_flags[ MAX_USER_FLAGS ][ MAX_ADMIN_FLAG_LEN ];
- char tail_flags[ MAX_USER_FLAGS ][ MAX_ADMIN_FLAG_LEN ];
- char allflag[ MAX_ADMIN_FLAG_LEN ];
- char newflag[ MAX_ADMIN_FLAG_LEN ];
- int head_count = 0;
- int tail_count = 0;
- qboolean flagset = qfalse;
- int i;
+ G_SanitiseString( testname, name, sizeof( name ) );
- if( !flag[ 0 ] )
- {
- return "invalid admin flag";
- }
-
- allflag[ 0 ] = '\0';
- token_p = oldflags;
- while( *( token = COM_Parse( &token_p ) ) )
+ if( vic )
+ a = vic->client->pers.admin;
+ else if( !a )
{
- key = token;
- if( *key == '-' || *key == '+' )
- key++;
+ g_admin_admin_t *wa;
+ int matches = 0;
- if( !strcmp( key, flag ) )
+ for( wa = g_admin_admins; wa && matches < 2; wa = wa->next )
{
- if( flagset )
- continue;
- flagset = qtrue;
- if( clear )
+ G_SanitiseString( wa->name, testname, sizeof( testname ) );
+ if( strstr( testname, name ) )
{
- // clearing ALLFLAGS will result in clearing any following flags
- if( !strcmp( key, ADMF_ALLFLAGS ) )
- break;
- else
- continue;
+ a = wa;
+ matches++;
}
- Com_sprintf( newflag, sizeof( newflag ), "%s%s",
- ( add ) ? "+" : "-", key );
- }
- else
- {
- Q_strncpyz( newflag, token, sizeof( newflag ) );
}
- if( !strcmp( key, ADMF_ALLFLAGS ) )
+ for( i = 0; i < level.maxclients && matches < 2; i++ )
{
- if( !allflag[ 0 ] )
- Q_strncpyz( allflag, newflag, sizeof( allflag ) );
- continue;
- }
+ if( level.clients[ i ].pers.connected == CON_DISCONNECTED )
+ continue;
- if( !allflag[ 0 ] )
- {
- if( head_count < MAX_USER_FLAGS )
+ if( matches && level.clients[ i ].pers.admin &&
+ level.clients[ i ].pers.admin == a )
{
- Q_strncpyz( head_flags[ head_count ], newflag,
- sizeof( head_flags[ head_count ] ) );
- head_count++;
+ vic = &g_entities[ i ];
+ continue;
}
- }
- else
- {
- if( tail_count < MAX_USER_FLAGS )
+
+ G_SanitiseString( level.clients[ i ].pers.netname, testname,
+ sizeof( testname ) );
+ if( strstr( testname, name ) )
{
- Q_strncpyz( tail_flags[ tail_count ], newflag,
- sizeof( tail_flags[ tail_count ] ) );
- tail_count++;
+ vic = &g_entities[ i ];
+ a = vic->client->pers.admin;
+ matches++;
}
}
- }
- if( !flagset && !clear )
- {
- if( !strcmp( flag, ADMF_ALLFLAGS ) )
+ if( matches == 0 )
{
- Com_sprintf( allflag, sizeof( allflag ), "%s%s",
- ( add ) ? "" : "-", ADMF_ALLFLAGS );
+ ADMP( "^3setlevel:^7 no match. use listplayers or listadmins to "
+ "find an appropriate number to use instead of name.\n" );
+ return qfalse;
}
- else if( !allflag[ 0 ] )
+ if( matches > 1 )
{
- if( head_count < MAX_USER_FLAGS )
- {
- Com_sprintf( head_flags[ head_count ], sizeof( head_flags[ head_count ] ),
- "%s%s", ( add ) ? "" : "-", flag );
- head_count++;
- }
- }
- else
- {
- if( tail_count < MAX_USER_FLAGS )
- {
- Com_sprintf( tail_flags[ tail_count ], sizeof( tail_flags[ tail_count ] ),
- "%s%s", ( add ) ? "+" : "-", flag );
- tail_count++;
- }
+ ADMP( "^3setlevel:^7 more than one match. Use the admin number "
+ "instead:\n" );
+ admin_listadmins( ent, 0, name );
+ return qfalse;
}
}
- qsort( head_flags, head_count, sizeof( head_flags[ 0 ] ), SortFlags );
- qsort( tail_flags, tail_count, sizeof( tail_flags[ 0 ] ), SortFlags );
-
- // rebuild flags
- newflags[ 0 ] = '\0';
- for( i = 0; i < head_count; i++ )
+ if( ent && !admin_higher_admin( ent->client->pers.admin, a ) )
{
- Q_strcat( newflags, size,
- va( "%s%s", ( i ) ? " ": "", head_flags[ i ] ) );
- }
- if( allflag[ 0 ] )
- {
- Q_strcat( newflags, size,
- va( "%s%s", ( newflags[ 0 ] ) ? " ": "", allflag ) );
-
- for( i = 0; i < tail_count; i++ )
- {
- Q_strcat( newflags, size,
- va( " %s", tail_flags[ i ] ) );
- }
+ ADMP( "^3setlevel: ^7sorry, but your intended victim has a higher"
+ " admin level than you\n" );
+ return qfalse;
}
- return NULL;
-}
-
-typedef struct {
- char *flag;
- char *description;
-} AdminFlagListEntry_t;
-static AdminFlagListEntry_t adminFlagList[] =
-{
- { ADMF_ACTIVITY, "inactivity rules do not apply" },
- { ADMF_ADMINCHAT, "can see and use admin chat" },
- { ADMF_HIGHADMINCHAT, "can see and use high admin chat" },
- { ADMF_ALLFLAGS, "has all flags and can use any command" },
- { ADMF_BAN_IMMUNITY, "immune from IP bans" },
- { ADMF_CAN_PERM_BAN, "can permanently ban players" },
- { ADMF_DBUILDER, "permanent designated builder" },
- { ADMF_FORCETEAMCHANGE, "team balance rules do not apply" },
- { ADMF_INCOGNITO, "does not show as admin in !listplayers" },
- { ADMF_SEESINCOGNITO, "sees registered name of players flagged with INCOGNITO" },
- { ADMF_IMMUNITY, "cannot be vote kicked or muted" },
- { ADMF_IMMUTABLE, "admin commands cannot be used on them" },
- { ADMF_NOCENSORFLOOD, "no flood protection" },
- { ADMF_NO_VOTE_LIMIT, "vote limitations do not apply" },
- { ADMF_SEESFULLLISTPLAYERS, "sees all info in !listplayers" },
- { ADMF_SPEC_ALLCHAT, "can see team chat as spectator" },
- { ADMF_ADMINSTEALTH, "uses admin stealth" },
- { 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_NOSCRIMRESTRICTION, "team joining, vote and chat restrictions during scrims do not apply" },
- { ADMF_NO_BUILD, "can not build" },
- { ADMF_NO_CHAT, "can not talk" },
- { ADMF_NO_VOTE, "can not call votes" },
- { ADMF_NOAUTOBAHN, "ignored by the Autobahn system" }
-};
-static int adminNumFlags= sizeof( adminFlagList ) / sizeof( adminFlagList[ 0 ] );
-
-#define MAX_LISTCOMMANDS 128
-qboolean G_admin_flaglist( gentity_t *ent, int skiparg )
-{
- qboolean shown[ MAX_LISTCOMMANDS ];
- int i, j;
- int count = 0;
-
- ADMBP_begin();
-
- ADMBP( "^3Ability flags:\n" );
-
- for( i = 0; i < adminNumFlags; i++ )
+ if( vic && vic->client->pers.guidless )
{
- ADMBP( va( " %s%-20s ^7%s\n",
- ( adminFlagList[ i ].flag[ 0 ] != '.' ) ? "^5" : "^1",
- adminFlagList[ i ].flag,
- adminFlagList[ i ].description ) );
+ ADMP( va( "^3setlevel: ^7%s^7 has no GUID\n", vic->client->pers.netname ) );
+ return qfalse;
}
- ADMBP( "^3Command flags:\n" );
-
- memset( shown, 0, sizeof( shown ) );
- for( i = 0; i < adminNumCmds; i++ )
+ if( !a && vic )
{
- if( i < MAX_LISTCOMMANDS && shown[ i ] )
- continue;
- ADMBP( va( " ^5%-20s^7", g_admin_cmds[ i ].flag ) );
- for( j = i; j < adminNumCmds; j++ )
- {
- if( !strcmp( g_admin_cmds[ j ].flag, g_admin_cmds[ i ].flag ) )
- {
- ADMBP( va( " %s", g_admin_cmds[ j ].keyword ) );
- if( j < MAX_LISTCOMMANDS )
- shown[ j ] = qtrue;
- }
- }
- ADMBP( "\n" );
- count++;
+ for( a = g_admin_admins; a && a->next; a = a->next );
+ if( a )
+ a = a->next = BG_Alloc( sizeof( g_admin_admin_t ) );
+ else
+ a = g_admin_admins = BG_Alloc( sizeof( g_admin_admin_t ) );
+ vic->client->pers.admin = a;
+ Q_strncpyz( a->guid, vic->client->pers.guid, sizeof( a->guid ) );
}
- ADMBP( va( "^3!flaglist: ^7listed %d abilities and %d command flags\n",
- adminNumFlags, count ) );
+ a->level = l->level;
+ if( vic )
+ Q_strncpyz( a->name, vic->client->pers.netname, sizeof( a->name ) );
- ADMBP_end();
+ admin_log( va( "%d (%s) \"%s" S_COLOR_WHITE "\"", a->level, a->guid,
+ a->name ) );
+
+ AP( va(
+ "print \"^3setlevel: ^7%s^7 was given level %d admin rights by %s\n\"",
+ a->name, a->level, ( ent ) ? ent->client->pers.netname : "console" ) );
+ admin_writeconfig();
+ if( vic )
+ {
+ G_admin_authlog( vic );
+ G_admin_cmdlist( vic );
+ }
return qtrue;
}
-qboolean G_admin_flag( gentity_t *ent, int skiparg )
+static void admin_create_ban( gentity_t *ent,
+ char *netname,
+ char *guid,
+ addr_t *ip,
+ int seconds,
+ char *reason )
{
- char command[ MAX_ADMIN_CMD_LEN ], *cmd;
- char name[ MAX_NAME_LENGTH ];
- char flagbuf[ MAX_ADMIN_FLAG_LEN ];
- char *flag;
- int id;
- char adminname[ MAX_NAME_LENGTH ] = {""};
- const char *result;
- qboolean add = qtrue;
- qboolean clear = qfalse;
- int admin_level = -1;
- int i, level;
-
- G_SayArgv( skiparg, command, sizeof( command ) );
- cmd = command;
- if( *cmd == '!' )
- cmd++;
-
- if( G_SayArgc() < 2 + skiparg )
- {
- ADMP( va( "^3!%s: ^7usage: !%s slot# flag\n", cmd, cmd ) );
- return qfalse;
- }
-
- G_SayArgv( 1 + skiparg, name, sizeof( name ) );
- if( name[ 0 ] == '*' )
- {
- if( ent )
- {
- ADMP( va( "^3!%s: only console can change admin level flags\n", cmd ) );
- return qfalse;
- }
- id = atoi( name + 1 );
- for( i = 0; i < MAX_ADMIN_LEVELS && g_admin_levels[ i ]; i++ )
- {
- if( g_admin_levels[ i ]->level == id )
- {
- admin_level = i;
- break;
- }
- }
- if( admin_level < 0 )
- {
- ADMP( va( "^3!%s: admin level %d does not exist\n", cmd, id ) );
- return qfalse;
- }
- Com_sprintf( adminname, sizeof( adminname ), "admin level %d", id );
- }
- else
- {
- id = G_admin_find_admin_slot( ent, name, cmd, adminname, sizeof( adminname ) );
- if( id < 0 )
- return qfalse;
+ g_admin_ban_t *b = NULL;
+ qtime_t qt;
+ int t;
+ int i;
+ char *name;
+ char disconnect[ MAX_STRING_CHARS ];
- if( ent && !admin_higher_guid( ent->client->pers.guid, g_admin_admins[ id ]->guid ) )
- {
- ADMP( va( "^3%s:^7 your intended victim has a higher admin level than you\n", cmd ) );
- return qfalse;
- }
- }
+ t = trap_RealTime( &qt );
- if( G_SayArgc() < 3 + skiparg )
+ for( b = g_admin_bans; b; b = b->next )
{
- flag = "";
- level = 0;
- if( admin_level < 0 )
- {
- for( i = 0; i < MAX_ADMIN_LEVELS && g_admin_levels[ i ]; i++ )
- {
- if( g_admin_admins[ id ]->level == g_admin_levels[ i ]->level )
- {
- flag = g_admin_levels[ i ]->flags;
- level = g_admin_admins[ id ]->level;
- break;
- }
- }
- ADMP( va( "^3%s:^7 flags for %s^7 are '^3%s^7'\n",
- cmd, adminname, g_admin_admins[ id ]->flags) );
- }
- else
- {
- flag = g_admin_levels[ admin_level ]->flags;
- level = g_admin_levels[ admin_level ]->level;
- }
- ADMP( va( "^3%s:^7 level %d flags are '%s'\n",
- cmd, level, flag ) );
-
- return qtrue;
+ if( !b->next )
+ break;
}
- G_SayArgv( 2 + skiparg, flagbuf, sizeof( flagbuf ) );
- flag = flagbuf;
- if( flag[ 0 ] == '-' || flag[ 0 ] == '+' )
- {
- add = ( flag[ 0 ] == '+' );
- flag++;
- }
- if( ent && !Q_stricmp( ent->client->pers.guid, g_admin_admins[ id ]->guid ) )
+ if( b )
{
- ADMP( va( "^3%s:^7 you may not change your own flags (use rcon)\n", cmd ) );
- return qfalse;
- }
- if( flag[ 0 ] != '.' && !G_admin_permission( ent, flag ) )
- {
- ADMP( va( "^3%s:^7 you can only change flags that you also have\n", cmd ) );
- return qfalse;
+ if( !b->next )
+ b = b->next = BG_Alloc( sizeof( g_admin_ban_t ) );
}
+ else
+ b = g_admin_bans = BG_Alloc( sizeof( g_admin_ban_t ) );
- if( !Q_stricmp( cmd, "unflag" ) )
- {
- clear = qtrue;
- }
+ Q_strncpyz( b->name, netname, sizeof( b->name ) );
+ Q_strncpyz( b->guid, guid, sizeof( b->guid ) );
+ memcpy( &b->ip, ip, sizeof( b->ip ) );
- if( admin_level < 0 )
- {
- result = G_admin_user_flag( g_admin_admins[ id ]->flags, flag, add, clear,
- g_admin_admins[ id ]->flags, sizeof( g_admin_admins[ id ]->flags ) );
- }
- else
- {
- result = G_admin_user_flag( g_admin_levels[ admin_level ]->flags, flag, add, clear,
- g_admin_levels[ admin_level ]->flags,
- sizeof( g_admin_levels[ admin_level ]->flags ) );
- }
- if( result )
- {
- ADMP( va( "^3!flag: ^7an error occured setting flag '^3%s^7', %s\n",
- flag, result ) );
- return qfalse;
- }
+ Com_sprintf( b->made, sizeof( b->made ), "%04i-%02i-%02i %02i:%02i:%02i",
+ qt.tm_year+1900, qt.tm_mon+1, qt.tm_mday,
+ qt.tm_hour, qt.tm_min, qt.tm_sec );
- if( !Q_stricmp( cmd, "flag" ) )
- {
- G_AdminsPrintf( "^3!%s: ^7%s^7 was %s admin flag '%s' by %s\n",
- cmd, adminname,
- ( add ) ? "given" : "denied",
- flag,
- ( ent ) ? ent->client->pers.netname : "console" );
- }
+ if( ent && ent->client->pers.admin )
+ name = ent->client->pers.admin->name;
+ else if( ent )
+ name = ent->client->pers.netname;
else
- {
- G_AdminsPrintf( "^3!%s: ^7admin flag '%s' for %s^7 cleared by %s\n",
- cmd, flag, adminname,
- ( ent ) ? ent->client->pers.netname : "console" );
- }
+ name = "console";
- if( !g_admin.string[ 0 ] )
- ADMP( va( "^3!%s: ^7WARNING g_admin not set, not saving admin record "
- "to a file\n", cmd ) );
+ Q_strncpyz( b->banner, name, sizeof( b->banner ) );
+ if( !seconds )
+ b->expires = 0;
else
- admin_writeconfig();
+ b->expires = t + seconds;
+ if( !*reason )
+ Q_strncpyz( b->reason, "banned by admin", sizeof( b->reason ) );
+ else
+ Q_strncpyz( b->reason, reason, sizeof( b->reason ) );
- return qtrue;
+ G_admin_ban_message( NULL, b, disconnect, sizeof( disconnect ), NULL, 0 );
+
+ for( i = 0; i < level.maxclients; i++ )
+ {
+ if( level.clients[ i ].pers.connected == CON_DISCONNECTED )
+ continue;
+ if( G_admin_ban_matches( b, &g_entities[ i ] ) )
+ {
+ trap_SendServerCommand( i, va( "disconnect \"%s\"", disconnect ) );
+
+ trap_DropClient( i, va( "has been kicked by %s^7. reason: %s",
+ b->banner, b->reason ) );
+ }
+ }
}
int G_admin_parse_time( const char *time )
{
int seconds = 0, num = 0;
- int i;
- for( i = 0; time[ i ]; i++ )
+ if( !*time )
+ return -1;
+ while( *time )
{
- if( isdigit( time[ i ] ) )
- {
- num = num * 10 + time[ i ] - '0';
- continue;
- }
- if( i == 0 || !isdigit( time[ i - 1 ] ) )
+ if( !isdigit( *time ) )
return -1;
- switch( time[ i ] )
+ while( isdigit( *time ) )
+ num = num * 10 + *time++ - '0';
+
+ if( !*time )
+ break;
+ switch( *time++ )
{
case 'w': num *= 7;
case 'd': num *= 24;
@@ -2653,2093 +1574,776 @@ int G_admin_parse_time( const char *time )
}
if( num )
seconds += num;
- // overflow
- if( seconds < 0 )
- seconds = 0;
return seconds;
}
-static qboolean admin_create_ban( gentity_t *ent,
- char *netname,
- char *guid,
- char *ip,
- int seconds,
- char *reason )
+qboolean G_admin_setdevmode( gentity_t *ent )
{
- g_admin_ban_t *b = NULL;
- qtime_t qt;
- int t;
- int i;
-
- t = trap_RealTime( &qt );
- b = G_Alloc( sizeof( g_admin_ban_t ) );
-
- if( !b )
+ char str[ 5 ];
+ if( trap_Argc() != 2 )
+ {
+ ADMP( "^3setdevmode: ^7usage: setdevmode [on|off]\n" );
return qfalse;
-
- Q_strncpyz( b->name, netname, sizeof( b->name ) );
- Q_strncpyz( b->guid, guid, sizeof( b->guid ) );
- Q_strncpyz( b->ip, ip, sizeof( b->ip ) );
- b->suspend = 0;
-
- //strftime( b->made, sizeof( b->made ), "%m/%d/%y %H:%M:%S", lt );
- Q_strncpyz( b->made, va( "%02i/%02i/%02i %02i:%02i:%02i",
- (qt.tm_mon + 1), qt.tm_mday, (qt.tm_year - 100),
- qt.tm_hour, qt.tm_min, qt.tm_sec ),
- sizeof( b->made ) );
-
- Q_strncpyz( b->banner, G_admin_get_adminname( ent ), sizeof( b->banner ) );
-
- if( ent )
- b->bannerlevel = G_admin_level( ent );
- else
- b->bannerlevel = 0;
-
- if( !seconds )
- b->expires = 0;
- else
- b->expires = t + seconds;
- if( !*reason )
- Q_strncpyz( b->reason, "banned by admin", sizeof( b->reason ) );
+ }
+ trap_Argv( 1, str, sizeof( str ) );
+ if( !Q_stricmp( str, "on" ) )
+ {
+ if( g_cheats.integer )
+ {
+ ADMP( "^3setdevmode: ^7developer mode is already on\n" );
+ return qfalse;
+ }
+ trap_Cvar_Set( "sv_cheats", "1" );
+ trap_Cvar_Update( &g_cheats );
+ AP( va( "print \"^3setdevmode: ^7%s ^7has switched developer mode on\n\"",
+ ent ? ent->client->pers.netname : "console" ) );
+ return qtrue;
+ }
+ else if( !Q_stricmp( str, "off" ) )
+ {
+ if( !g_cheats.integer )
+ {
+ ADMP( "^3setdevmode: ^7developer mode is already off\n" );
+ return qfalse;
+ }
+ trap_Cvar_Set( "sv_cheats", "0" );
+ trap_Cvar_Update( &g_cheats );
+ AP( va( "print \"^3setdevmode: ^7%s ^7has switched developer mode off\n\"",
+ ent ? ent->client->pers.netname : "console" ) );
+ return qtrue;
+ }
else
- Q_strncpyz( b->reason, reason, sizeof( b->reason ) );
- for( i = 0; i < MAX_ADMIN_BANS && g_admin_bans[ i ]; i++ )
- ;
- if( i == MAX_ADMIN_BANS )
{
- ADMP( "^3!ban: ^7too many bans\n" );
- G_Free( b );
+ ADMP( "^3setdevmode: ^7usage: setdevmode [on|off]\n" );
return qfalse;
}
- g_admin_bans[ i ] = b;
- return qtrue;
}
-qboolean G_admin_kick( gentity_t *ent, int skiparg )
+qboolean G_admin_kick( gentity_t *ent )
{
- int pids[ MAX_CLIENTS ];
+ int pid;
char name[ MAX_NAME_LENGTH ], *reason, err[ MAX_STRING_CHARS ];
int minargc;
gentity_t *vic;
- char notice[51];
-
- trap_Cvar_VariableStringBuffer( "g_banNotice", notice, sizeof( notice ) );
- minargc = 3 + skiparg;
+ minargc = 3;
if( G_admin_permission( ent, ADMF_UNACCOUNTABLE ) )
- minargc = 2 + skiparg;
+ minargc = 2;
- if( G_SayArgc() < minargc )
+ if( trap_Argc() < minargc )
{
- ADMP( "^3!kick: ^7usage: !kick [name] [reason]\n" );
+ ADMP( "^3kick: ^7usage: kick [name] [reason]\n" );
return qfalse;
}
- G_SayArgv( 1 + skiparg, name, sizeof( name ) );
- reason = G_SayConcatArgs( 2 + skiparg );
- if( G_ClientNumbersFromString( name, pids ) != 1 )
+ trap_Argv( 1, name, sizeof( name ) );
+ reason = ConcatArgs( 2 );
+ if( ( pid = G_ClientNumberFromString( name, err, sizeof( err ) ) ) == -1 )
{
- G_MatchOnePlayer( pids, err, sizeof( err ) );
- ADMP( va( "^3!kick: ^7%s\n", err ) );
+ ADMP( va( "^3kick: ^7%s", err ) );
return qfalse;
}
- if( !admin_higher( ent, &g_entities[ pids[ 0 ] ] ) )
+ vic = &g_entities[ pid ];
+ if( !admin_higher( ent, vic ) )
{
- ADMP( "^3!kick: ^7sorry, but your intended victim has a higher admin"
+ ADMP( "^3kick: ^7sorry, but your intended victim has a higher admin"
" level than you\n" );
return qfalse;
}
- vic = &g_entities[ pids[ 0 ] ];
+ if( vic->client->pers.localClient )
+ {
+ ADMP( "^3kick: ^7disconnecting the host would end the game\n" );
+ return qfalse;
+ }
+ admin_log( va( "%d (%s) \"%s" S_COLOR_WHITE "\": \"%s" S_COLOR_WHITE "\"",
+ pid,
+ vic->client->pers.guid,
+ vic->client->pers.netname,
+ reason ) );
admin_create_ban( ent,
vic->client->pers.netname,
- vic->client->pers.guid,
- vic->client->pers.ip, G_admin_parse_time( g_adminTempBan.string ),
+ vic->client->pers.guidless ? "" : vic->client->pers.guid,
+ &vic->client->pers.ip,
+ MAX( 1, G_admin_parse_time( g_adminTempBan.string ) ),
( *reason ) ? reason : "kicked by admin" );
- if( g_admin.string[ 0 ] )
- admin_writeconfig();
-
- trap_SendServerCommand( pids[ 0 ],
- va( "disconnect \"You have been kicked.\n%s^7\nreason:\n%s\n%s\"",
- ( ent ) ? va( "admin:\n%s", G_admin_adminPrintName( ent ) ) : "admin\nconsole",
- ( *reason ) ? reason : "kicked by admin", notice ) );
-
- trap_DropClient( pids[ 0 ], va( "kicked%s^7, reason: %s",
- ( ent ) ? va( " by %s", G_admin_adminPrintName( ent ) ) : " by console",
- ( *reason ) ? reason : "kicked by admin" ) );
+ admin_writeconfig();
return qtrue;
}
-qboolean G_admin_ban( gentity_t *ent, int skiparg )
+qboolean G_admin_setivo( gentity_t* ent )
{
- int seconds;
- char search[ MAX_NAME_LENGTH ];
- char secs[ 7 ];
- char *reason;
- int minargc;
- char duration[ 32 ];
- int logmatch = -1, logmatches = 0;
- int i, j;
- qboolean exactmatch = qfalse;
- char n2[ MAX_NAME_LENGTH ];
- char s2[ MAX_NAME_LENGTH ];
- char guid_stub[ 9 ];
- char notice[51];
-
- 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_adminMaxBan.integer ) ||
- G_admin_permission( ent, ADMF_UNACCOUNTABLE ) )
- {
- minargc = 3 + skiparg;
- }
- else
- {
- minargc = 4 + skiparg;
- }
- if( G_SayArgc() < minargc )
+ char arg[ 3 ];
+ const char *cn;
+ gentity_t *spot;
+
+ if( !ent )
{
- ADMP( "^3!ban: ^7usage: !ban [name|slot|ip] [time] [reason]\n" );
+ ADMP( "^3setivo: ^7the console can't position intermission view overrides\n" );
return qfalse;
}
- G_SayArgv( 1 + skiparg, search, sizeof( search ) );
- G_SanitiseString( search, s2, sizeof( s2 ) );
- G_SayArgv( 2 + skiparg, secs, sizeof( secs ) );
- seconds = G_admin_parse_time( secs );
- if( seconds <= 0 )
+ if( trap_Argc() != 2 )
{
- if( g_adminMaxBan.integer && !G_admin_permission( ent, ADMF_CAN_PERM_BAN ) )
- {
- ADMP( va( "^3!ban: ^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!ban: ^7ban time must be positive\n" );
- return qfalse;
- }
- reason = G_SayConcatArgs( 2 + skiparg );
+ ADMP( "^3setivo: ^7usage: setivo {s|a|h}\n" );
+ return qfalse;
}
+ trap_Argv( 1, arg, sizeof( arg ) );
+ if( !Q_stricmp( arg, "s" ) )
+ cn = "info_player_intermission";
+ else if( !Q_stricmp( arg, "a" ) )
+ cn = "info_alien_intermission";
+ else if( !Q_stricmp( arg, "h" ) )
+ cn = "info_human_intermission";
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!ban: ^7ban length limited to %s for your admin level\n",
- g_adminMaxBan.string ) );
- }
- }
-
- for( i = 0; i < MAX_ADMIN_NAMELOGS && g_admin_namelog[ i ]; i++ )
- {
- // skip players in the namelog who have already been banned
- if( g_admin_namelog[ i ]->banned )
- continue;
-
- // skip disconnected players when banning on slot number
- 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++ )
- {
- // skip players in the namelog who have already been banned
- if( g_admin_namelog[ i ]->banned )
- continue;
-
- if( !Q_stricmp( g_admin_namelog[ i ]->ip, s2 ) )
- {
- logmatches = 1;
- logmatch = i;
- exactmatch = qtrue;
- break;
- }
- 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!ban: ^7no player found by that name, IP, or slot number\n" );
- return qfalse;
- }
- else if( logmatches > 1 )
- {
- ADMBP_begin();
- ADMBP( "^3!ban: ^7multiple recent clients match name, use IP or slot#:\n" );
- for( i = 0; i < MAX_ADMIN_NAMELOGS && g_admin_namelog[ i ]; i++ )
- {
- for( j = 0; j < 8; j++ )
- guid_stub[ j ] = g_admin_namelog[ i ]->guid[ j + 24 ];
- guid_stub[ j ] = '\0';
- 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 (*%s) %15s ^7'%s^7'\n",
- (g_admin_namelog[ i ]->slot > -1) ?
- va( "%d", g_admin_namelog[ i ]->slot ) : "-",
- guid_stub,
- g_admin_namelog[ i ]->ip,
- g_admin_namelog[ i ]->name[ j ] ) );
- }
- }
- }
- ADMBP_end();
+ ADMP( "^3setivo: ^7the argument must be either s, a or h\n" );
return qfalse;
}
-
- G_admin_duration( ( seconds ) ? seconds : -1,
- duration, sizeof( duration ) );
- if( ent && !admin_higher_guid( ent->client->pers.guid,
- g_admin_namelog[ logmatch ]->guid ) )
+ spot = G_Find( NULL, FOFS( classname ), cn );
+ if( !spot )
{
-
- ADMP( "^3!ban: ^7sorry, but your intended victim has a higher admin"
- " level than you\n" );
- return qfalse;
+ spot = G_Spawn();
+ spot->classname = (char *)cn;
}
+ spot->count = 1;
- admin_create_ban( ent,
- g_admin_namelog[ logmatch ]->name[ 0 ],
- g_admin_namelog[ logmatch ]->guid,
- g_admin_namelog[ logmatch ]->ip,
- seconds, reason );
-
- g_admin_namelog[ logmatch ]->banned = qtrue;
+ BG_GetClientViewOrigin( &ent->client->ps, spot->r.currentOrigin );
+ VectorCopy( ent->client->ps.viewangles, spot->r.currentAngles );
- if( !g_admin.string[ 0 ] )
- ADMP( "^3!ban: ^7WARNING g_admin not set, not saving ban to a file\n" );
- else
- admin_writeconfig();
-
- if( g_admin_namelog[ logmatch ]->slot == -1 )
- {
- // client is already disconnected so stop here
- AP( va( "print \"^3!ban:^7 %s^7 has been banned by %s^7 "
- "duration: %s, reason: %s\n\"",
- g_admin_namelog[ logmatch ]->name[ 0 ],
- ( ent ) ? G_admin_adminPrintName( ent ) : "console",
- duration,
- ( *reason ) ? reason : "banned by admin" ) );
- return qtrue;
- }
-
- trap_SendServerCommand( g_admin_namelog[ logmatch ]->slot,
- va( "disconnect \"You have been banned.\n"
- "admin:\n%s^7\nduration:\n%s\nreason:\n%s\n%s\"",
- ( ent ) ? G_admin_adminPrintName( ent ) : "console",
- duration,
- ( *reason ) ? reason : "banned by admin", notice ) );
-
- trap_DropClient( g_admin_namelog[ logmatch ]->slot,
- va( "banned by %s^7, duration: %s, reason: %s",
- ( ent ) ? G_admin_adminPrintName( ent ) : "console",
- duration,
- ( *reason ) ? reason : "banned by admin" ) );
+ ADMP( "^3setivo: ^7intermission view override positioned\n" );
return qtrue;
}
-// If true then don't let the player join a team, use the chat or run commands.
-qboolean G_admin_is_restricted(gentity_t *ent, qboolean sendMessage)
+qboolean G_admin_ban( gentity_t *ent )
{
- schachtmeisterJudgement_t *j = NULL;
- int i;
-
- // Never restrict admins or whitelisted players.
- if (G_admin_permission(ent, ADMF_NOAUTOBAHN) ||
- G_admin_permission(ent, ADMF_IMMUNITY))
- return qfalse;
-
- // Find the relevant namelog.
- // FIXME: this shouldn't require looping over *all* namelogs.
- for (i = 0; i < MAX_ADMIN_NAMELOGS && g_admin_namelog[i]; i++) {
- if (g_admin_namelog[i]->slot == ent - g_entities) {
- j = &g_admin_namelog[i]->smj;
- break;
- }
- }
-
- // A missing namelog shouldn't happen.
- if (!j)
- return qfalse;
-
- // Restrictions concern only unrated players.
- if (j->ratingTime)
- return qfalse;
-
- // Don't wait forever, allow up to 15 seconds.
- if (level.time - j->queryTime >= 15000)
- return qfalse;
-
- if (sendMessage)
- trap_SendServerCommand(ent - g_entities, "print \"Please wait a moment before doing anything.\n\"");
-
- return qtrue;
-}
-
-static void admin_autobahn(gentity_t *ent, int rating)
-{
- // Allow per-GUID exceptions and never autoban admins.
- if (G_admin_permission(ent, ADMF_NOAUTOBAHN) ||
- G_admin_permission(ent, ADMF_IMMUNITY))
- return;
-
- // Don't do anything if the rating is clear.
- if (rating >= g_schachtmeisterClearThreshold.integer)
- return;
-
- // Ban only if the rating is low enough.
- if (rating > g_schachtmeisterAutobahnThreshold.integer) {
- G_AdminsPrintf("%s^7 (#%d) has rating %d\n",
- ent->client->pers.netname, ent - g_entities,
- rating);
- return;
- }
-
- G_LogAutobahn(ent, NULL, rating, qfalse);
-
- trap_SendServerCommand(ent - g_entities, va("disconnect \"%s\"\n",
- g_schachtmeisterAutobahnMessage.string));
- trap_DropClient(ent - g_entities, "dropped by the Autobahn");
-}
-
-void G_admin_IPA_judgement( const char *ipa, int rating, const char *comment )
-{
- int i;
- for( i = 0; i < MAX_ADMIN_NAMELOGS && g_admin_namelog[ i ]; i++ )
- {
- if( !strcmp( g_admin_namelog[ i ]->ip, ipa ) )
- {
- schachtmeisterJudgement_t *j = &g_admin_namelog[ i ]->smj;
-
- j->ratingTime = level.time;
- j->queryTime = 0;
- j->dispatchTime = 0;
-
- j->rating = rating;
-
- if( j->comment )
- G_Free( j->comment );
-
- if( comment )
- {
- j->comment = G_Alloc( strlen( comment ) + 1 );
- strcpy( j->comment, comment );
- }
- else
- j->comment = NULL;
-
- if( g_admin_namelog[ i ]->slot != -1 )
- admin_autobahn( g_entities + g_admin_namelog[ i ]->slot, j->rating );
- }
- }
-}
-
-qboolean G_admin_adjustban( gentity_t *ent, int skiparg )
-{
- int bnum;
- int length;
- int expires;
- int time = trap_RealTime( NULL );
- char duration[ 32 ] = {""};
- char *reason;
- char bs[ 5 ];
+ int seconds;
+ char search[ MAX_NAME_LENGTH ];
char secs[ MAX_TOKEN_CHARS ];
- char mode = '\0';
+ char *reason;
+ char duration[ MAX_DURATION_LENGTH ];
+ int i;
+ addr_t ip;
+ qboolean ipmatch = qfalse;
+ namelog_t *match = NULL;
+ qboolean cidr = qfalse;
- if( G_SayArgc() < 3 + skiparg )
+ if( trap_Argc() < 2 )
{
- ADMP( "^3!adjustban: ^7usage: !adjustban [ban#] [time] [reason]\n" );
+ ADMP( "^3ban: ^7usage: ban [name|slot|IP(/mask)] [duration] [reason]\n" );
return qfalse;
}
- G_SayArgv( 1 + skiparg, bs, sizeof( bs ) );
- bnum = atoi( bs );
- if( bnum < 1 || bnum > MAX_ADMIN_BANS || !g_admin_bans[ bnum - 1] )
+ trap_Argv( 1, search, sizeof( search ) );
+ trap_Argv( 2, secs, sizeof( secs ) );
+
+ seconds = G_admin_parse_time( secs );
+ if( seconds <= 0 )
{
- ADMP( "^3!adjustban: ^7invalid ban#\n" );
- return qfalse;
+ seconds = 0;
+ reason = ConcatArgs( 2 );
}
- if( g_admin_bans[ bnum - 1 ]->expires == 0 &&
- !G_admin_permission( ent, ADMF_CAN_PERM_BAN ) )
+ else
{
- ADMP( "^3!adjustban: ^7you cannot modify permanent bans\n" );
- return qfalse;
+ reason = ConcatArgs( 3 );
}
- if( g_admin_bans[ bnum - 1 ]->bannerlevel > G_admin_level( ent ) )
+ if( !*reason && !G_admin_permission( ent, ADMF_UNACCOUNTABLE ) )
{
- ADMP( "^3!adjustban: ^7you cannot modify Bans made by admins higher than you\n" );
+ ADMP( "^3ban: ^7you must specify a reason\n" );
return qfalse;
}
- if( g_adminMaxBan.integer &&
- !G_admin_permission( ent, ADMF_CAN_PERM_BAN ) &&
- g_admin_bans[ bnum - 1 ]->expires - time > G_admin_parse_time( g_adminMaxBan.string ) )
+ if( !G_admin_permission( ent, ADMF_CAN_PERM_BAN ) )
{
- ADMP( va( "^3!adjustban: ^7your admin level cannot modify bans longer than %s\n",
- g_adminMaxBan.string ) );
- return qfalse;
- }
- G_SayArgv( 2 + skiparg, secs, sizeof( secs ) );
- if( secs[ 0 ] == '+' || secs[ 0 ] == '-' )
- mode = secs[ 0 ];
- length = G_admin_parse_time( &secs[ mode ? 1 : 0 ] );
- if( length < 0 )
- skiparg--;
- else
- {
- if( length )
+ int maximum = MAX( 1, G_admin_parse_time( g_adminMaxBan.string ) );
+ if( seconds == 0 || seconds > maximum )
{
- if( g_admin_bans[ bnum - 1 ]->expires == 0 && mode )
- {
- ADMP( "^3!adjustban: ^7new duration must be explicit\n" );
- return qfalse;
- }
- if( mode == '+' )
- expires = g_admin_bans[ bnum - 1 ]->expires + length;
- else if( mode == '-' )
- expires = g_admin_bans[ bnum - 1 ]->expires - length;
- else
- expires = time + length;
- if( expires <= time )
- {
- ADMP( "^3!adjustban: ^7ban time must be positive\n" );
- return qfalse;
- }
- if( g_adminMaxBan.integer &&
- !G_admin_permission( ent, ADMF_CAN_PERM_BAN ) &&
- expires - time > G_admin_parse_time( g_adminMaxBan.string ) )
- {
- ADMP( va( "^3!adjustban: ^7ban length is limited to %s for your admin level\n",
- g_adminMaxBan.string ) );
- length = G_admin_parse_time( g_adminMaxBan.string );
- expires = time + length;
- }
+ ADMP( "^3ban: ^7you may not issue permanent bans\n" );
+ seconds = maximum;
}
- else if( G_admin_permission( ent, ADMF_CAN_PERM_BAN ) )
- expires = 0;
+ }
+
+ if( G_AddressParse( search, &ip ) )
+ {
+ int max = ip.type == IPv4 ? 32 : 128;
+ int min;
+
+ cidr = G_admin_permission( ent, ADMF_CAN_IP_BAN );
+ if( cidr )
+ min = ent ? max / 2 : 1;
else
+ min = max;
+
+ if( ip.mask < min || ip.mask > max )
{
- ADMP( "^3!adjustban: ^7ban time must be positive\n" );
+ ADMP( va( "^3ban: ^7invalid netmask (%d is not in the range %d-%d)\n",
+ ip.mask, min, max ) );
return qfalse;
}
+ ipmatch = qtrue;
- g_admin_bans[ bnum - 1 ]->expires = expires;
- G_admin_duration( ( expires ) ? expires - time : -1,
- duration, sizeof( duration ) );
- }
- reason = G_SayConcatArgs( 3 + skiparg );
- if( *reason )
- Q_strncpyz( g_admin_bans[ bnum - 1 ]->reason, reason,
- sizeof( g_admin_bans[ bnum - 1 ]->reason ) );
- AP( va( "print \"^3!adjustban: ^7ban #%d for %s^7 has been updated by %s^7 "
- "%s%s%s%s%s\n\"",
- bnum,
- g_admin_bans[ bnum - 1 ]->name,
- ( ent ) ? G_admin_adminPrintName( ent ) : "console",
- ( length >= 0 ) ? "duration: " : "",
- duration,
- ( length >= 0 && *reason ) ? ", " : "",
- ( *reason ) ? "reason: " : "",
- reason ) );
- if( ent ) {
- Q_strncpyz( g_admin_bans[ bnum - 1 ]->banner, G_admin_get_adminname( ent ),
- sizeof( g_admin_bans[ bnum - 1 ]->banner ) );
- g_admin_bans[ bnum - 1 ]->bannerlevel = G_admin_level( ent );
- }
-
- if( g_admin.string[ 0 ] )
- admin_writeconfig();
- return qtrue;
-}
-
+ for( match = level.namelogs; match; match = match->next )
+ {
+ // skip players in the namelog who have already been banned
+ if( match->banned )
+ continue;
-qboolean G_admin_subnetban( gentity_t *ent, int skiparg )
-{
- int bnum;
- int mask;
- unsigned int IPRlow = 0, IPRhigh = 0;
- char cIPRlow[ 32 ], cIPRhigh[ 32 ];
- char bs[ 5 ];
- char strmask[ 5 ];
- char exl[2];
- int k, IP[5];
-
- if( G_SayArgc() < 3 + skiparg )
- {
- ADMP( "^3!subnetban: ^7usage: !subnetban [ban#] [mask]\n" );
- return qfalse;
- }
- G_SayArgv( 1 + skiparg, bs, sizeof( bs ) );
- bnum = atoi( bs );
- if( bnum < 1 || bnum > MAX_ADMIN_BANS || !g_admin_bans[ bnum - 1] )
- {
- ADMP( "^3!subnetban: ^7invalid ban#\n" );
- return qfalse;
- }
- if( g_admin_bans[ bnum - 1 ]->bannerlevel > G_admin_level( ent ) )
- {
- ADMP( "^3!subnetban: ^7you cannot subnetban Bans on bans made by admins higher than you\n" );
- return qfalse;
- }
+ for( i = 0; i < MAX_NAMELOG_ADDRS && match->ip[ i ].str[ 0 ]; i++ )
+ {
+ if( G_AddressCompare( &ip, &match->ip[ i ] ) )
+ break;
+ }
+ if( i < MAX_NAMELOG_ADDRS && match->ip[ i ].str[ 0 ] )
+ break;
+ }
- G_SayArgv( 2 + skiparg, strmask, sizeof( strmask ) );
- mask = atoi( strmask );
-
- if( mask >= 0 && mask <= 32)
- {
- G_SayArgv( 3 + skiparg, exl, sizeof( exl ) );
- if( mask >= 0 && mask < 16 )
+ if( !match )
{
- if( ent )
+ if( cidr )
{
- ADMP( "^3!subnetban: ^7Only console may ban such a large network. Regular admins may only ban >=16.\n" );
- return qfalse;
+ ADMP( "^3ban: ^7no player found by that IP address; banning anyway\n" );
}
- if( strcmp(exl, "!") )
+ else
{
- ADMP( "^3!subnetban: ^1WARNING:^7 you are about to ban a large network, use !subnetban [ban] [mask] ! to force^7\n" );
+ ADMP( "^3ban: ^7no player found by that IP address\n" );
return qfalse;
}
}
-
- memset( IP, 0, sizeof( IP ) );
- sscanf(g_admin_bans[ bnum - 1 ]->ip, "%d.%d.%d.%d/%d", &IP[4], &IP[3], &IP[2], &IP[1], &IP[0]);
- for(k = 4; k >= 1; k--)
- {
- if( IP[k] )
- IPRlow |= IP[k] << 8*(k-1);
- }
- IPRhigh = IPRlow;
- if( mask == 32 )
- {
- Q_strncpyz(
- g_admin_bans[ bnum - 1 ]->ip,
- va("%i.%i.%i.%i", IP[4], IP[3], IP[2], IP[1]),
- sizeof( g_admin_bans[ bnum - 1 ]->ip )
- );
- }
- else
- {
- Q_strncpyz(
- g_admin_bans[ bnum - 1 ]->ip,
- va("%i.%i.%i.%i/%i", IP[4], IP[3], IP[2], IP[1], mask ),
- sizeof( g_admin_bans[ bnum - 1 ]->ip )
- );
- IPRlow &= ~((1 << (32-mask)) - 1);
- IPRhigh |= ((1 << (32-mask)) - 1);
- }
}
- else
+ else if( !( match = G_NamelogFromString( ent, search ) ) || match->banned )
{
- ADMP( "^3!subnetban: ^7mask is out of range, please use 0-32 inclusive\n" );
+ ADMP( "^3ban: ^7no match\n" );
return qfalse;
}
- if( mask > 0 )
- {
- Q_strncpyz(
- cIPRlow,
- va("%u.%u.%u.%u", (IPRlow & (255 << 24)) >> 24, (IPRlow & (255 << 16)) >> 16, (IPRlow & (255 << 8)) >> 8, IPRlow & 255),
- sizeof( cIPRlow )
- );
- Q_strncpyz(
- cIPRhigh,
- va("%u.%u.%u.%u", (IPRhigh & (255 << 24)) >> 24, (IPRhigh & (255 << 16)) >> 16, (IPRhigh & (255 << 8)) >> 8, IPRhigh & 255),
- sizeof( cIPRhigh )
- );
- }
- else
- {
- Q_strncpyz( cIPRlow, "0.0.0.0", sizeof( cIPRlow ) );
- Q_strncpyz( cIPRhigh, "255.255.255.255", sizeof( cIPRhigh ) );
-
- }
-
- AP( va( "print \"^3!subnetban: ^7ban #%d for %s^7 has been updated by %s^7 "
- "%s (%s - %s)\n\"",
- bnum,
- g_admin_bans[ bnum - 1 ]->name,
- ( ent ) ? G_admin_adminPrintName( ent ) : "console",
- g_admin_bans[ bnum - 1 ]->ip,
- cIPRlow,
- cIPRhigh) );
- if( ent )
- Q_strncpyz( g_admin_bans[ bnum - 1 ]->banner, G_admin_get_adminname( ent ),
- sizeof( g_admin_bans[ bnum - 1 ]->banner ) );
- if( g_admin.string[ 0 ] )
- admin_writeconfig();
- return qtrue;
-}
-
-qboolean G_admin_suspendban( gentity_t *ent, int skiparg )
-{
- int bnum;
- int length;
- int timenow = 0;
- int expires = 0;
- char *arg;
- char bs[ 5 ];
- char duration[ 32 ];
- qtime_t qt;
- if( G_SayArgc() < 3 + skiparg )
- {
- ADMP( "^3!suspendban: ^7usage: !suspendban [ban #] [length]\n" );
- return qfalse;
- }
- G_SayArgv( 1 + skiparg, bs, sizeof( bs ) );
- bnum = atoi( bs );
- if( bnum < 1 || !g_admin_bans[ bnum - 1] )
+ if( ent && match && !admin_higher_guid( ent->client->pers.guid, match->guid ) )
{
- ADMP( "^3!suspendban: ^7invalid ban #\n" );
+
+ ADMP( "^3ban: ^7sorry, but your intended victim has a higher admin"
+ " level than you\n" );
return qfalse;
}
- if( g_admin_bans[ bnum - 1 ]->bannerlevel > G_admin_level( ent ) )
+ if( match && match->slot > -1 && level.clients[ match->slot ].pers.localClient )
{
- ADMP( "^3!suspendban: ^7you cannot suspend Bans made by admins higher than you\n" );
+ ADMP( "^3ban: ^7disconnecting the host would end the game\n" );
return qfalse;
}
- arg = G_SayConcatArgs( 2 + skiparg );
- timenow = trap_RealTime( &qt );
- length = G_admin_parse_time( arg );
-
- if( length < 0 )
- {
- ADMP( "^3!suspendban: ^7invalid length\n" );
- return qfalse;
- }
- if( length > MAX_ADMIN_BANSUSPEND_DAYS * 24 * 60 * 60 )
- {
- length = MAX_ADMIN_BANSUSPEND_DAYS * 24 * 60 * 60;
- ADMP( va( "^3!suspendban: ^7maximum ban suspension is %d days\n",
- MAX_ADMIN_BANSUSPEND_DAYS ) );
- } else if( g_admin_bans[ bnum - 1 ]->expires > 0 && length + timenow > g_admin_bans[ bnum - 1 ]->expires ) {
- length = g_admin_bans[ bnum - 1 ]->expires - timenow;
- G_admin_duration( length , duration, sizeof( duration ) );
- ADMP( va( "^3!suspendban: ^7Suspension Duration trimmed to Ban duration: %s\n",
- duration ) );
- }
+ G_admin_duration( ( seconds ) ? seconds : -1,
+ duration, sizeof( duration ) );
- if ( length > 0 )
- {
- expires = timenow + length;
- }
- if( g_admin_bans[ bnum - 1 ]->suspend == expires )
- {
- ADMP( "^3!suspendban: ^7no change\n" );
- return qfalse;
- }
+ AP( va( "print \"^3ban:^7 %s^7 has been banned by %s^7 "
+ "duration: %s, reason: %s\n\"",
+ match ? match->name[ match->nameOffset ] : "an IP address",
+ ( ent ) ? ent->client->pers.netname : "console",
+ duration,
+ ( *reason ) ? reason : "banned by admin" ) );
- g_admin_bans[ bnum - 1 ]->suspend = expires;
- if ( length > 0 )
+ admin_log( va( "%d (%s) \"%s" S_COLOR_WHITE "\": \"%s" S_COLOR_WHITE "\"",
+ seconds,
+ match ? match->guid : "",
+ match ? match->name[ match->nameOffset ] : "IP ban",
+ reason ) );
+ if( ipmatch )
{
- G_admin_duration( length , duration, sizeof( duration ) );
- AP( va( "print \"^3!suspendban: ^7ban #%d suspended for %s\n\"",
- bnum, duration ) );
+ if( match )
+ {
+ admin_create_ban( ent,
+ match->slot == -1 ?
+ match->name[ match->nameOffset ] :
+ level.clients[ match->slot ].pers.netname,
+ match->guidless ? "" : match->guid,
+ &ip,
+ seconds, reason );
+ }
+ else
+ {
+ admin_create_ban( ent, "IP ban", "", &ip, seconds, reason );
+ }
+ admin_log( va( "[%s]", ip.str ) );
}
else
{
- AP( va( "print \"^3!suspendban: ^7ban #%d suspension removed\n\"",
- bnum ) );
+ // ban all IP addresses used by this player
+ for( i = 0; i < MAX_NAMELOG_ADDRS && match->ip[ i ].str[ 0 ]; i++ )
+ {
+ admin_create_ban( ent,
+ match->slot == -1 ?
+ match->name[ match->nameOffset ] :
+ level.clients[ match->slot ].pers.netname,
+ match->guidless ? "" : match->guid,
+ &match->ip[ i ],
+ seconds, reason );
+ admin_log( va( "[%s]", match->ip[ i ].str ) );
+ }
}
+ if( match )
+ match->banned = qtrue;
+
if( !g_admin.string[ 0 ] )
- ADMP( "^3!adjustban: ^7WARNING g_admin not set, not saving ban to a file\n" );
+ ADMP( "^3ban: ^7WARNING g_admin not set, not saving ban to a file\n" );
else
admin_writeconfig();
+
return qtrue;
}
-qboolean G_admin_unban( gentity_t *ent, int skiparg )
+qboolean G_admin_unban( gentity_t *ent )
{
int bnum;
+ int time = trap_RealTime( NULL );
char bs[ 5 ];
- int t;
+ int i;
+ g_admin_ban_t *ban;
- t = trap_RealTime( NULL );
- if( G_SayArgc() < 2 + skiparg )
+ if( trap_Argc() < 2 )
{
- ADMP( "^3!unban: ^7usage: !unban [ban#]\n" );
+ ADMP( "^3unban: ^7usage: unban [ban#]\n" );
return qfalse;
}
- G_SayArgv( 1 + skiparg, bs, sizeof( bs ) );
+ trap_Argv( 1, bs, sizeof( bs ) );
bnum = atoi( bs );
- if( bnum < 1 || bnum > MAX_ADMIN_BANS || !g_admin_bans[ bnum - 1 ] )
- {
- ADMP( "^3!unban: ^7invalid ban#\n" );
- return qfalse;
- }
- if( g_admin_bans[ bnum - 1 ]->expires == 0 &&
- !G_admin_permission( ent, ADMF_CAN_PERM_BAN ) )
+ for( ban = g_admin_bans, i = 1; ban && i < bnum; ban = ban->next, i++ )
+ ;
+ if( i != bnum || !ban )
{
- ADMP( "^3!unban: ^7you cannot remove permanent bans\n" );
+ ADMP( "^3unban: ^7invalid ban#\n" );
return qfalse;
}
- if( g_admin_bans[ bnum - 1 ]->bannerlevel > G_admin_level( ent ) )
+ if( ban->expires > 0 && ban->expires - time <= 0 )
{
- ADMP( "^3!unban: ^7you cannot Remove Bans made by admins higher than you\n" );
+ ADMP( "^3unban: ^7ban already expired\n" );
return qfalse;
}
- if( g_adminMaxBan.integer &&
- !G_admin_permission( ent, ADMF_CAN_PERM_BAN ) &&
- g_admin_bans[ bnum - 1 ]->expires - t > G_admin_parse_time( g_adminMaxBan.string ) )
+ if( !G_admin_permission( ent, ADMF_CAN_PERM_BAN ) &&
+ ( ban->expires == 0 || ( ban->expires - time > MAX( 1,
+ G_admin_parse_time( g_adminMaxBan.string ) ) ) ) )
{
- ADMP( va( "^3!unban: ^7your admin level cannot remove bans longer than %s\n",
- g_adminMaxBan.string ) );
+ ADMP( "^3unban: ^7you cannot remove permanent bans\n" );
return qfalse;
}
- g_admin_bans[ bnum -1 ]->expires = t;
- AP( va( "print \"^3!unban: ^7ban #%d for %s^7 has been removed by %s\n\"",
+ admin_log( va( "%d (%s) \"%s" S_COLOR_WHITE "\": \"%s" S_COLOR_WHITE "\": [%s]",
+ ban->expires ? ban->expires - time : 0, ban->guid, ban->name, ban->reason,
+ ban->ip.str ) );
+ AP( va( "print \"^3unban: ^7ban #%d for %s^7 has been removed by %s\n\"",
bnum,
- g_admin_bans[ bnum - 1 ]->name,
- ( ent ) ? G_admin_adminPrintName( ent ) : "console" ) );
- if( g_admin.string[ 0 ] )
- admin_writeconfig();
+ ban->name,
+ ( ent ) ? ent->client->pers.netname : "console" ) );
+ ban->expires = time;
+ admin_writeconfig();
return qtrue;
}
-qboolean G_admin_putteam( gentity_t *ent, int skiparg )
+qboolean G_admin_addlayout( gentity_t *ent )
{
- int pids[ MAX_CLIENTS ];
- char name[ MAX_NAME_LENGTH ], team[ 7 ], err[ MAX_STRING_CHARS ];
- gentity_t *vic;
- pTeam_t teamnum = PTE_NONE;
- char teamdesc[ 32 ] = {"spectators"};
- char secs[ 7 ];
- int seconds = 0;
- qboolean useDuration = qfalse;
-
- G_SayArgv( 1 + skiparg, name, sizeof( name ) );
- G_SayArgv( 2 + skiparg, team, sizeof( team ) );
- if( G_SayArgc() < 3 + skiparg )
- {
- ADMP( "^3!putteam: ^7usage: !putteam [name] [h|a|s] (duration)\n" );
- return qfalse;
- }
-
- if( G_ClientNumbersFromString( name, pids ) != 1 )
- {
- G_MatchOnePlayer( pids, err, sizeof( err ) );
- ADMP( va( "^3!putteam: ^7%s\n", err ) );
- return qfalse;
- }
- if( !admin_higher( ent, &g_entities[ pids[ 0 ] ] ) )
- {
- ADMP( "^3!putteam: ^7sorry, but your intended victim has a higher "
- " admin level than you\n" );
- return qfalse;
- }
- vic = &g_entities[ pids[ 0 ] ];
+ char layout[ MAX_QPATH ];
- if ( vic->client->sess.invisible == qtrue )
+ if( trap_Argc( ) != 2 )
{
- ADMP( "^3!putteam: ^7invisible players cannot join a team\n" );
+ ADMP( "^3addlayout: ^7usage: addlayout <layoutelements>\n" );
return qfalse;
}
- switch( team[ 0 ] )
- {
- case 'a':
- teamnum = PTE_ALIENS;
- Q_strncpyz( teamdesc, "aliens", sizeof( teamdesc ) );
- break;
- case 'h':
- teamnum = PTE_HUMANS;
- Q_strncpyz( teamdesc, "humans", sizeof( teamdesc ) );
- break;
- case 's':
- teamnum = PTE_NONE;
- break;
- default:
- ADMP( va( "^3!putteam: ^7unknown team %c\n", team[ 0 ] ) );
- return qfalse;
- }
- //duration code
- if( G_SayArgc() > 3 + skiparg ) {
- //can only lock players in spectator
- if ( teamnum != PTE_NONE )
- {
- ADMP( "^3!putteam: ^7You can only lock a player into the spectators team\n" );
- return qfalse;
- }
- G_SayArgv( 3 + skiparg, secs, sizeof( secs ) );
- seconds = G_admin_parse_time( secs );
- useDuration = qtrue;
- }
+ trap_Argv( 1, layout, sizeof( layout ) );
- if( vic->client->pers.teamSelection == teamnum && teamnum != PTE_NONE )
- {
- ADMP( va( "^3!putteam: ^7%s ^7is already on the %s team\n", vic->client->pers.netname, teamdesc ) );
- return qfalse;
- }
+ G_LayoutLoad( layout );
- if( useDuration == qtrue && seconds > 0 ) {
- vic->client->pers.specExpires = level.time + ( seconds * 1000 );
- }
- G_ChangeTeam( vic, teamnum );
-
- AP( va( "print \"^3!putteam: ^7%s^7 put %s^7 on to the %s team%s\n\"",
- ( ent ) ? G_admin_adminPrintName( ent ) : "console",
- vic->client->pers.netname, teamdesc,
- ( seconds ) ? va( " for %i seconds", seconds ) : "" ) );
+ AP( va( "print \"^3addlayout: ^7some layout elements have been placed by %s\n\"",
+ ent ? ent->client->pers.netname : "console" ) );
return qtrue;
}
-qboolean G_admin_seen(gentity_t *ent, int skiparg )
+qboolean G_admin_adjustban( gentity_t *ent )
{
- char name[ MAX_NAME_LENGTH ];
- char search[ MAX_NAME_LENGTH ];
- char sduration[ 32 ];
- qboolean numeric = qtrue;
- int i, j;
- int id = -1;
- int count = 0;
- int t;
- qtime_t qt;
- gentity_t *vic;
- qboolean ison;
+ int bnum;
+ int length, maximum;
+ int expires;
+ int time = trap_RealTime( NULL );
+ char duration[ MAX_DURATION_LENGTH ] = {""};
+ char *reason;
+ char bs[ 5 ];
+ char secs[ MAX_TOKEN_CHARS ];
+ char mode = '\0';
+ g_admin_ban_t *ban;
+ int mask = 0;
+ int i;
+ int skiparg = 0;
- if( G_SayArgc() < 2 + skiparg )
+ if( trap_Argc() < 3 )
{
- ADMP( "^3!seen: ^7usage: !seen [name|admin#]\n" );
+ ADMP( "^3adjustban: ^7usage: adjustban [ban#] [/mask] [duration] [reason]"
+ "\n" );
return qfalse;
}
- G_SayArgv( 1 + skiparg, name, sizeof( name ) );
- G_SanitiseString( name, search, sizeof( search ) );
- for( i = 0; i < sizeof( search ) && search[ i ] ; i++ )
+ trap_Argv( 1, bs, sizeof( bs ) );
+ bnum = atoi( bs );
+ for( ban = g_admin_bans, i = 1; ban && i < bnum; ban = ban->next, i++ );
+ if( i != bnum || !ban )
{
- if( search[ i ] < '0' || search[ i ] > '9' )
- {
- numeric = qfalse;
- break;
- }
+ ADMP( "^3adjustban: ^7invalid ban#\n" );
+ return qfalse;
}
-
- if( numeric )
+ maximum = MAX( 1, G_admin_parse_time( g_adminMaxBan.string ) );
+ if( !G_admin_permission( ent, ADMF_CAN_PERM_BAN ) &&
+ ( ban->expires == 0 || ban->expires - time > maximum ) )
{
- id = atoi( name );
- search[ 0 ] = '\0';
+ ADMP( "^3adjustban: ^7you cannot modify permanent bans\n" );
+ return qfalse;
}
-
- ADMBP_begin();
- t = trap_RealTime( &qt );
-
- for( i = 0; i < level.maxclients && count < 10; i ++ )
+ trap_Argv( 2, secs, sizeof( secs ) );
+ if( secs[ 0 ] == '/' )
{
- vic = &g_entities[ i ];
+ int max = ban->ip.type == IPv6 ? 128 : 32;
+ int min;
- if( !vic->client || vic->client->pers.connected != CON_CONNECTED )
- continue;
-
- G_SanitiseString( vic->client->pers.netname, name, sizeof( name ) );
+ if( G_admin_permission( ent, ADMF_CAN_IP_BAN ) )
+ min = ent ? max / 2 : 1;
+ else
+ min = max;
- if( i == id || (search[ 0 ] && strstr( name, search ) ) )
+ mask = atoi( secs + 1 );
+ if( mask < min || mask > max )
{
- if ( vic->client->sess.invisible == qfalse )
- {
- ADMBP( va( "^3%4d ^7%s^7 is currently playing\n", i, vic->client->pers.netname ) );
- count++;
- }
+ ADMP( va( "^3adjustban: ^7invalid netmask (%d is not in range %d-%d)\n",
+ mask, min, max ) );
+ return qfalse;
}
+ trap_Argv( 3 + skiparg++, secs, sizeof( secs ) );
}
- for( i = 0; i < MAX_ADMIN_ADMINS && g_admin_admins[ i ] && count < 10; i++ )
+ if( secs[ 0 ] == '+' || secs[ 0 ] == '-' )
+ mode = secs[ 0 ];
+ length = G_admin_parse_time( &secs[ mode ? 1 : 0 ] );
+ if( length < 0 )
+ skiparg--;
+ else
{
- G_SanitiseString( g_admin_admins[ i ]->name, name, sizeof( name ) );
- if( i + MAX_CLIENTS == id || (search[ 0 ] && strstr( name, search ) ) )
+ if( length )
{
- ison = qfalse;
- for( j = 0; j < level.maxclients; j++ )
+ if( ban->expires == 0 && mode )
{
- vic = &g_entities[ j ];
- if( !vic->client || vic->client->pers.connected != CON_CONNECTED )
- continue;
- G_SanitiseString( vic->client->pers.netname, name, sizeof( name ) );
- if( !Q_stricmp( vic->client->pers.guid, g_admin_admins[ i ]->guid )
- && strstr( name, search ) )
- {
- if ( vic->client->sess.invisible == qfalse )
- {
- ison = qtrue;
- break;
- }
- }
- }
-
- if( ison )
- {
- if( id == -1 )
- continue;
- ADMBP( va( "^3%4d ^7%s^7 is currently playing\n",
- i + MAX_CLIENTS, g_admin_admins[ i ]->name ) );
+ ADMP( "^3adjustban: ^7new duration must be explicit\n" );
+ return qfalse;
}
+ if( mode == '+' )
+ expires = ban->expires + length;
+ else if( mode == '-' )
+ expires = ban->expires - length;
else
+ expires = time + length;
+ if( expires <= time )
{
- G_admin_duration( t - g_admin_admins[ i ]->seen,
- sduration, sizeof( sduration ) );
- ADMBP( va( "%4d %s^7 last seen %s%s\n",
- i + MAX_CLIENTS, g_admin_admins[ i ]->name ,
- ( g_admin_admins[ i ]->seen ) ? sduration : "",
- ( g_admin_admins[ i ]->seen ) ? " ago" : "time is unknown" ) );
+ ADMP( "^3adjustban: ^7ban duration must be positive\n" );
+ return qfalse;
}
- count++;
- }
- }
-
- if( search[ 0 ] )
- ADMBP( va( "^3!seen:^7 found %d player%s matching '%s'\n",
- count, (count == 1) ? "" : "s", search ) );
- else if ( !count )
- ADMBP( "^3!seen:^7 no one connectd by that slot number\n" );
-
- ADMBP_end();
- return qtrue;
-}
-
-void G_admin_seen_update( char *guid )
-{
- int i;
-
- for( i = 0; i < MAX_ADMIN_ADMINS && g_admin_admins[ i ] ; i++ )
- {
- if( !Q_stricmp( g_admin_admins[ i ]->guid, guid ) )
- {
- qtime_t qt;
-
- g_admin_admins[ i ]->seen = trap_RealTime( &qt );
- return;
}
- }
-}
-
-void G_admin_adminlog_cleanup( void )
-{
- int i;
-
- for( i = 0; i < MAX_ADMIN_ADMINLOGS && g_admin_adminlog[ i ]; i++ )
- {
- G_Free( g_admin_adminlog[ i ] );
- g_admin_adminlog[ i ] = NULL;
- }
-
- admin_adminlog_index = 0;
-}
-
-void G_admin_adminlog_log( gentity_t *ent, char *command, char *args, int skiparg, qboolean success )
-{
- g_admin_adminlog_t *adminlog;
- int previous;
- int count = 1;
- int i;
-
- if( !command )
- return;
-
- if( !Q_stricmp( command, "adminlog" ) ||
- !Q_stricmp( command, "admintest" ) ||
- !Q_stricmp( command, "help" ) ||
- !Q_stricmp( command, "info" ) ||
- !Q_stricmp( command, "listadmins" ) ||
- !Q_stricmp( command, "listplayers" ) ||
- !Q_stricmp( command, "namelog" ) ||
- !Q_stricmp( command, "showbans" ) ||
- !Q_stricmp( command, "seen" ) ||
- !Q_stricmp( command, "time" ) )
- return;
-
- previous = admin_adminlog_index - 1;
- if( previous < 0 )
- previous = MAX_ADMIN_ADMINLOGS - 1;
-
- if( g_admin_adminlog[ previous ] )
- count = g_admin_adminlog[ previous ]->id + 1;
-
- if( g_admin_adminlog[ admin_adminlog_index ] )
- adminlog = g_admin_adminlog[ admin_adminlog_index ];
- else
- adminlog = G_Alloc( sizeof( g_admin_adminlog_t ) );
-
- memset( adminlog, 0, sizeof( *adminlog ) );
- adminlog->id = count;
- adminlog->time = level.time - level.startTime;
- adminlog->success = success;
- Q_strncpyz( adminlog->command, command, sizeof( adminlog->command ) );
-
- if ( args )
- Q_strncpyz( adminlog->args, args, sizeof( adminlog->args ) );
- else
- Q_strncpyz( adminlog->args, G_SayConcatArgs( 1 + skiparg ), sizeof( adminlog->args ) );
-
- if( ent )
- {
- qboolean found = qfalse;
- // real admin name
- for( i = 0; i < MAX_ADMIN_ADMINS && g_admin_admins[ i ]; i++ )
+ else
+ length = expires = 0;
+ if( !G_admin_permission( ent, ADMF_CAN_PERM_BAN ) &&
+ ( length == 0 || length > maximum ) )
{
- if( !Q_stricmp( g_admin_admins[ i ]->guid, ent->client->pers.guid ) )
- {
- Q_strncpyz( adminlog->name, g_admin_admins[ i ]->name, sizeof( adminlog->name ) );
- found = qtrue;
- break;
- }
+ ADMP( "^3adjustban: ^7you may not issue permanent bans\n" );
+ expires = time + maximum;
}
- if( !found )
- Q_strncpyz( adminlog->name, ent->client->pers.netname, sizeof( adminlog->name ) );
- adminlog->level = ent->client->pers.adminLevel;
+ ban->expires = expires;
+ G_admin_duration( ( expires ) ? expires - time : -1, duration,
+ sizeof( duration ) );
}
- else
+ if( mask )
{
- Q_strncpyz( adminlog->name, "console", sizeof( adminlog->name ) );
- adminlog->level = 10000;
+ char *p = strchr( ban->ip.str, '/' );
+ if( !p )
+ p = ban->ip.str + strlen( ban->ip.str );
+ if( mask == ( ban->ip.type == IPv6 ? 128 : 32 ) )
+ *p = '\0';
+ else
+ Com_sprintf( p, sizeof( ban->ip.str ) - ( p - ban->ip.str ), "/%d", mask );
+ ban->ip.mask = mask;
}
-
- g_admin_adminlog[ admin_adminlog_index ] = adminlog;
- admin_adminlog_index++;
- if( admin_adminlog_index >= MAX_ADMIN_ADMINLOGS )
- admin_adminlog_index = 0;
+ reason = ConcatArgs( 3 + skiparg );
+ if( *reason )
+ Q_strncpyz( ban->reason, reason, sizeof( ban->reason ) );
+ admin_log( va( "%d (%s) \"%s" S_COLOR_WHITE "\": \"%s" S_COLOR_WHITE "\": [%s]",
+ ban->expires ? ban->expires - time : 0, ban->guid, ban->name, ban->reason,
+ ban->ip.str ) );
+ AP( va( "print \"^3adjustban: ^7ban #%d for %s^7 has been updated by %s^7 "
+ "%s%s%s%s%s%s\n\"",
+ bnum,
+ ban->name,
+ ( ent ) ? ent->client->pers.netname : "console",
+ ( mask ) ?
+ va( "netmask: /%d%s", mask,
+ ( length >= 0 || *reason ) ? ", " : "" ) : "",
+ ( length >= 0 ) ? "duration: " : "",
+ duration,
+ ( length >= 0 && *reason ) ? ", " : "",
+ ( *reason ) ? "reason: " : "",
+ reason ) );
+ if( ent )
+ Q_strncpyz( ban->banner, ent->client->pers.netname, sizeof( ban->banner ) );
+ admin_writeconfig();
+ return qtrue;
}
-qboolean G_admin_adminlog( gentity_t *ent, int skiparg )
+qboolean G_admin_putteam( gentity_t *ent )
{
- g_admin_adminlog_t *results[ 10 ];
- int result_index = 0;
- char *search_cmd = NULL;
- char *search_name = NULL;
- int index;
- int skip = 0;
- int skipped = 0;
- int checked = 0;
- char n1[ MAX_NAME_LENGTH ];
- char fmt_name[ 16 ];
- char argbuf[ 32 ];
- int name_length = 12;
- int max_id = 0;
- int i;
- qboolean match;
-
- memset( results, 0, sizeof( results ) );
-
- index = admin_adminlog_index;
- for( i = 0; i < 10; i++ )
- {
- int prev;
-
- prev = index - 1;
- if( prev < 0 )
- prev = MAX_ADMIN_ADMINLOGS - 1;
- if( !g_admin_adminlog[ prev ] )
- break;
- if( g_admin_adminlog[ prev ]->id > max_id )
- max_id = g_admin_adminlog[ prev ]->id;
- index = prev;
- }
-
- if( G_SayArgc() > 1 + skiparg )
- {
- G_SayArgv( 1 + skiparg, argbuf, sizeof( argbuf ) );
- if( ( *argbuf >= '0' && *argbuf <= '9' ) || *argbuf == '-' )
- {
- int id;
-
- id = atoi( argbuf );
- if( id < 0 )
- id += ( max_id - 9 );
- else if( id <= max_id - MAX_ADMIN_ADMINLOGS )
- id = max_id - MAX_ADMIN_ADMINLOGS + 1;
-
- if( id + 9 >= max_id )
- id = max_id - 9;
- if( id < 1 )
- id = 1;
- for( i = 0; i < MAX_ADMIN_ADMINLOGS; i++ )
- {
- if( g_admin_adminlog[i] && g_admin_adminlog[ i ]->id == id )
- {
- index = i;
- break;
- }
- }
- }
- else if ( *argbuf == '!' )
- {
- search_cmd = argbuf + 1;
- }
- else
- {
- search_name = argbuf;
- }
-
- if( G_SayArgc() > 2 + skiparg && ( search_cmd || search_name ) )
- {
- char skipbuf[ 4 ];
- G_SayArgv( 2 + skiparg, skipbuf, sizeof( skipbuf ) );
- skip = atoi( skipbuf );
- }
- }
-
- if( search_cmd || search_name )
- {
- g_admin_adminlog_t *result_swap[ 10 ];
-
- memset( result_swap, 0, sizeof( result_swap ) );
-
- index = admin_adminlog_index - 1;
- if( index < 0 )
- index = MAX_ADMIN_ADMINLOGS - 1;
-
- while( g_admin_adminlog[ index ] &&
- checked < MAX_ADMIN_ADMINLOGS &&
- result_index < 10 )
- {
- match = qfalse;
- if( search_cmd )
- {
- if( !Q_stricmp( search_cmd, g_admin_adminlog[ index ]->command ) )
- match = qtrue;
- }
- if( search_name )
- {
- G_SanitiseString( g_admin_adminlog[ index ]->name, n1, sizeof( n1 ) );
- if( strstr( n1, search_name ) )
- match = qtrue;
- }
-
- if( match && skip > 0 )
- {
- match = qfalse;
- skip--;
- skipped++;
- }
- if( match )
- {
- result_swap[ result_index ] = g_admin_adminlog[ index ];
- result_index++;
- }
-
- checked++;
- index--;
- if( index < 0 )
- index = MAX_ADMIN_ADMINLOGS - 1;
- }
- // search runs backwards, turn it around
- for( i = 0; i < result_index; i++ )
- results[ i ] = result_swap[ result_index - i - 1 ];
- }
- else
- {
- while( g_admin_adminlog[ index ] && result_index < 10 )
- {
- results[ result_index ] = g_admin_adminlog[ index ];
- result_index++;
- index++;
- if( index >= MAX_ADMIN_ADMINLOGS )
- index = 0;
- }
- }
+ int pid;
+ char name[ MAX_NAME_LENGTH ], team[ sizeof( "spectators" ) ],
+ err[ MAX_STRING_CHARS ];
+ gentity_t *vic;
+ team_t teamnum = TEAM_NONE;
- for( i = 0; results[ i ] && i < 10; i++ )
+ trap_Argv( 1, name, sizeof( name ) );
+ trap_Argv( 2, team, sizeof( team ) );
+ if( trap_Argc() < 3 )
{
- int l;
-
- G_DecolorString( results[ i ]->name, n1 );
- l = strlen( n1 );
- if( l > name_length )
- name_length = l;
- }
- ADMBP_begin( );
- for( i = 0; results[ i ] && i < 10; i++ )
- {
- char levelbuf[ 8 ];
- int t;
-
- t = results[ i ]->time / 1000;
- G_DecolorString( results[ i ]->name, n1 );
- Com_sprintf( fmt_name, sizeof( fmt_name ), "%%%ds",
- ( name_length + strlen( results[ i ]->name ) - strlen( n1 ) ) );
- Com_sprintf( n1, sizeof( n1 ), fmt_name, results[ i ]->name );
- Com_sprintf( levelbuf, sizeof( levelbuf ), "%2d", results[ i ]->level );
- ADMBP( va( "%s%3d %3d:%02d %2s ^7%s^7 %s!%s ^7%s^7\n",
- ( results[ i ]->success ) ? "^7" : "^1",
- results[ i ]->id,
- t / 60, t % 60,
- ( results[ i ]->level ) < 10000 ? levelbuf : " -",
- n1,
- ( results[ i ]->success ) ? "^3" : "^1",
- results[ i ]->command,
- results[ i ]->args ) );
- }
- if( search_cmd || search_name )
- {
- ADMBP( va( "^3!adminlog:^7 Showing %d matches for '%s^7'.",
- result_index,
- argbuf ) );
- if( checked < MAX_ADMIN_ADMINLOGS && g_admin_adminlog[ checked ] )
- ADMBP( va( " run '!adminlog %s^7 %d' to see more",
- argbuf,
- skipped + result_index ) );
- ADMBP( "\n" );
- }
- else if ( results[ 0 ] )
- {
- ADMBP( va( "^3!adminlog:^7 Showing %d - %d of %d.\n",
- results[ 0 ]->id,
- results[ result_index - 1 ]->id,
- max_id ) );
- }
- else
- {
- ADMBP( "^3!adminlog:^7 log is empty.\n" );
+ ADMP( "^3putteam: ^7usage: putteam [name] [h|a|s]\n" );
+ return qfalse;
}
- ADMBP_end( );
- return qtrue;
-}
-
-qboolean G_admin_map( gentity_t *ent, int skiparg )
-{
- char map[ MAX_QPATH ];
- char layout[ MAX_QPATH ] = { "" };
-
- if( G_SayArgc( ) < 2 + skiparg )
+ if( ( pid = G_ClientNumberFromString( name, err, sizeof( err ) ) ) == -1 )
{
- ADMP( "^3!map: ^7usage: !map [map] (layout)\n" );
+ ADMP( va( "^3putteam: ^7%s", err ) );
return qfalse;
}
-
- G_SayArgv( skiparg + 1, map, sizeof( map ) );
-
- if( !trap_FS_FOpenFile( va( "maps/%s.bsp", map ), NULL, FS_READ ) )
+ vic = &g_entities[ pid ];
+ if( !admin_higher( ent, vic ) )
{
- ADMP( va( "^3!map: ^7invalid map name '%s'\n", map ) );
+ ADMP( "^3putteam: ^7sorry, but your intended victim has a higher "
+ " admin level than you\n" );
return qfalse;
}
-
- if( G_SayArgc( ) > 2 + skiparg )
+ teamnum = G_TeamFromString( team );
+ if( teamnum == NUM_TEAMS )
{
- G_SayArgv( skiparg + 2, layout, sizeof( layout ) );
- if( !Q_stricmp( layout, "*BUILTIN*" ) ||
- trap_FS_FOpenFile( va( "layouts/%s/%s.dat", map, layout ),
- NULL, FS_READ ) > 0 )
- {
- trap_Cvar_Set( "g_layouts", layout );
- }
- else
- {
- ADMP( va( "^3!map: ^7invalid layout name '%s'\n", layout ) );
- return qfalse;
- }
+ ADMP( va( "^3putteam: ^7unknown team %s\n", team ) );
+ return qfalse;
}
+ if( vic->client->pers.teamSelection == teamnum )
+ return qfalse;
+ admin_log( va( "%d (%s) \"%s" S_COLOR_WHITE "\"", pid, vic->client->pers.guid,
+ vic->client->pers.netname ) );
+ G_ChangeTeam( vic, teamnum );
- trap_SendConsoleCommand( EXEC_APPEND, va( "map %s", map ) );
- level.restarted = qtrue;
- AP( va( "print \"^3!map: ^7map '%s' started by %s^7 %s\n\"", map,
- ( ent ) ? G_admin_adminPrintName( ent ) : "console",
- ( layout[ 0 ] ) ? va( "(forcing layout '%s')", layout ) : "" ) );
- G_admin_maplog_result( "M" );
+ AP( va( "print \"^3putteam: ^7%s^7 put %s^7 on to the %s team\n\"",
+ ( ent ) ? ent->client->pers.netname : "console",
+ vic->client->pers.netname, BG_TeamName( teamnum ) ) );
return qtrue;
}
-qboolean G_admin_devmap( gentity_t *ent, int skiparg )
+qboolean G_admin_changemap( gentity_t *ent )
{
char map[ MAX_QPATH ];
char layout[ MAX_QPATH ] = { "" };
- if( G_SayArgc( ) < 2 + skiparg )
+ if( trap_Argc( ) < 2 )
{
- ADMP( "^3!devmap: ^7usage: !devmap [map] (layout)\n" );
+ ADMP( "^3changemap: ^7usage: changemap [map] (layout)\n" );
return qfalse;
}
- G_SayArgv( skiparg + 1, map, sizeof( map ) );
+ trap_Argv( 1, map, sizeof( map ) );
- if( !trap_FS_FOpenFile( va( "maps/%s.bsp", map ), NULL, FS_READ ) )
+ if( !G_MapExists( map ) )
{
- ADMP( va( "^3!devmap: ^7invalid map name '%s'\n", map ) );
+ ADMP( va( "^3changemap: ^7invalid map name '%s'\n", map ) );
return qfalse;
}
- if( G_SayArgc( ) > 2 + skiparg )
+ if( trap_Argc( ) > 2 )
{
- G_SayArgv( skiparg + 2, layout, sizeof( layout ) );
- if( !Q_stricmp( layout, "*BUILTIN*" ) ||
- trap_FS_FOpenFile( va( "layouts/%s/%s.dat", map, layout ),
- NULL, FS_READ ) > 0 )
+ trap_Argv( 2, layout, sizeof( layout ) );
+ if( G_LayoutExists( map, layout ) )
{
- trap_Cvar_Set( "g_layouts", layout );
+ trap_Cvar_Set( "g_nextLayout", layout );
}
else
{
- ADMP( va( "^3!devmap: ^7invalid layout name '%s'\n", layout ) );
+ ADMP( va( "^3changemap: ^7invalid layout name '%s'\n", layout ) );
return qfalse;
}
}
+ admin_log( map );
+ admin_log( layout );
- trap_SendConsoleCommand( EXEC_APPEND, va( "devmap %s", map ) );
+ G_MapConfigs( map );
+ trap_SendConsoleCommand( EXEC_APPEND, va( "%smap \"%s\"\n",
+ ( g_cheats.integer ? "dev" : "" ), map ) );
level.restarted = qtrue;
- AP( va( "print \"^3!devmap: ^7map '%s' started by %s^7 with cheats %s\n\"", map,
- ( ent ) ? G_admin_adminPrintName( ent ) : "console",
+ AP( va( "print \"^3changemap: ^7map '%s' started by %s^7 %s\n\"", map,
+ ( ent ) ? ent->client->pers.netname : "console",
( layout[ 0 ] ) ? va( "(forcing layout '%s')", layout ) : "" ) );
- G_admin_maplog_result( "D" );
return qtrue;
}
-void G_admin_maplog_update( void )
+qboolean G_admin_mute( gentity_t *ent )
{
- char map[ 64 ];
- char maplog[ MAX_CVAR_VALUE_STRING ];
- char *ptr;
- int count = 0;
-
- trap_Cvar_VariableStringBuffer( "mapname", map, sizeof( map ) );
-
- Q_strncpyz( maplog, g_adminMapLog.string, sizeof( maplog ) );
- ptr = maplog;
- while( *ptr && count < MAX_ADMIN_MAPLOG_LENGTH )
- {
- while( *ptr != ' ' && *ptr != '\0' ) ptr++;
-
- count++;
- if( count >= MAX_ADMIN_MAPLOG_LENGTH )
- {
- *ptr = '\0';
- }
-
- if( *ptr == ' ' ) ptr++;
- }
-
- trap_Cvar_Set( "g_adminMapLog", va( "%s%s%s",
- map,
- ( maplog[0] != '\0' ) ? " " : "",
- maplog ) );
-}
-
-void G_admin_maplog_result( char *flag )
-{
- static int lastTime = 0;
- char maplog[ MAX_CVAR_VALUE_STRING ];
- int t;
-
- if( !flag )
- return;
-
- // avoid race when called in same frame
- if( level.time == lastTime )
- return;
-
- lastTime = level.time;
-
- if( g_adminMapLog.string[ 0 ] &&
- g_adminMapLog.string[ 1 ] == ';' )
- {
- // only one result allowed
- return;
- }
-
- if ( level.surrenderTeam != PTE_NONE )
- {
- if( flag[ 0 ] == 'a' )
- {
- if( level.surrenderTeam == PTE_HUMANS )
- flag = "A";
- }
- else if( flag[ 0 ] == 'h' )
- {
- if( level.surrenderTeam == PTE_ALIENS )
- flag = "H";
- }
- }
-
- t = ( level.time - level.startTime ) / 1000;
- Q_strncpyz( maplog, g_adminMapLog.string, sizeof( maplog ) );
- trap_Cvar_Set( "g_adminMapLog", va( "%1s;%03d:%02d;%s",
- flag,
- t / 60, t % 60,
- maplog ) );
-}
-
-
-qboolean G_admin_maplog( gentity_t *ent, int skiparg )
-{
- char maplog[ MAX_CVAR_VALUE_STRING ];
- char *ptr;
- int count = 0;
-
- Q_strncpyz( maplog, g_adminMapLog.string, sizeof( maplog ) );
-
- ADMBP_begin( );
- ptr = maplog;
- while( *ptr != '\0' && count < MAX_ADMIN_MAPLOG_LENGTH + 1 )
- {
- char *end;
- const char *result = NULL;
- char *clock = NULL;
- char *colon;
-
- end = ptr;
- while( *end != ' ' && *end != '\0' ) end++;
- if( *end == ' ' )
- {
- *end = '\0';
- end++;
- }
-
- if( ptr[ 0 ] && ptr[ 1 ] == ';' )
- {
- switch( ptr[ 0 ] )
- {
- case 't':
- result = "^7tie";
- break;
- case 'a':
- result = "^1Alien win";
- break;
- case 'A':
- result = "^1Alien win ^7/ Humans admitted defeat";
- break;
- case 'h':
- result = "^4Human win";
- break;
- case 'H':
- result = "^4Human win ^7/ Aliens admitted defeat";
- break;
- case 'd':
- result = "^5draw vote";
- break;
- case 'N':
- result = "^6admin loaded next map";
- break;
- case 'r':
- result = "^2restart vote";
- break;
- case 'R':
- result = "^6admin restarted map";
- break;
- case 'm':
- result = "^2map vote";
- break;
- case 'M':
- result = "^6admin changed map";
- break;
- case 'D':
- result = "^6admin loaded devmap";
- break;
- default:
- result = "";
- break;
- }
- ptr += 2;
- colon = strchr( ptr, ';' );
- if ( colon )
- {
- clock = ptr;
- ptr = colon + 1;
- *colon = '\0';
-
- // right justification with -6%s doesnt work..
- if( clock[ 0 ] == '0' && clock[ 1 ] != ':' )
- {
- if( clock[ 1 ] == '0' && clock[ 2 ] != ':' )
- clock[ 1 ] = ' ';
- clock[ 0 ] = ' ';
- }
- }
- }
- else if( count == 0 )
- {
- result = "^3current map";
- clock = " -:--";
- }
-
- ADMBP( va( "%s%20s %-6s %s^7\n",
- ( count == 0 ) ? "^3" : "^7",
- ptr,
- ( clock ) ? clock : "",
- ( result ) ? result : "" ) );
-
- ptr = end;
- count++;
- }
- ADMBP_end( );
-
- return qtrue;
-}
-
-qboolean G_admin_layoutsave( gentity_t *ent, int skiparg )
-{
- char layout[ MAX_QPATH ];
-
- if( G_SayArgc( ) < 2 + skiparg )
- {
- ADMP( "^3!layoutsave: ^7usage: !layoutsave [layout]\n" );
- return qfalse;
- }
-
- G_SayArgv( skiparg + 1, layout, sizeof( layout ) );
-
- trap_SendConsoleCommand( EXEC_APPEND, va( "layoutsave %s", layout ) );
- AP( va( "print \"^3!layoutsave: ^7layout saved as '%s' by %s\n\"", layout,
- ( ent ) ? G_admin_adminPrintName( ent ) : "console" ) );
- return qtrue;
-}
-
-qboolean G_admin_demo( gentity_t *ent, int skiparg )
-{
- if( !ent )
- {
- ADMP( "!demo: console can not use demo.\n" );
- return qfalse;
- }
-
- ent->client->pers.ignoreAdminWarnings = !( ent->client->pers.ignoreAdminWarnings );
-
- ADMP( va( "^3!demo: ^7your visibility of admin chat is now %s\n",
- ( ent->client->pers.ignoreAdminWarnings ) ? "^1disabled" : "^2enabled" ) );
-
- return qtrue;
-}
-
-qboolean G_admin_mute( gentity_t *ent, int skiparg )
-{
- int pids[ MAX_CLIENTS ];
- char name[ MAX_NAME_LENGTH ], err[ MAX_STRING_CHARS ];
- char command[ MAX_ADMIN_CMD_LEN ], *cmd;
- gentity_t *vic;
- char secs[ 7 ];
- int seconds = 0;
-
- G_SayArgv( skiparg, command, sizeof( command ) );
- cmd = command;
-
- if( cmd && *cmd == '!' )
- cmd++;
-
- if( G_SayArgc() < 2 + skiparg )
- {
- ADMP( va( "^3!%s: ^7usage: !%s [name|slot#] (duration)\n", cmd, cmd ) );
- return qfalse;
- }
-
- G_SayArgv( 1 + skiparg, name, sizeof( name ) );
-
- if( G_ClientNumbersFromString( name, pids ) != 1 )
- {
- G_MatchOnePlayer( pids, err, sizeof( err ) );
- ADMP( va( "^3!%s: ^7%s\n", cmd, err ) );
- return qfalse;
- }
-
- if( !admin_higher( ent, &g_entities[ pids[ 0 ] ] ) )
- {
- ADMP( va( "^3!%s: ^7sorry, but your intended victim has a higher admin"
- " level than you\n", cmd ) );
- return qfalse;
- }
-
- vic = &g_entities[ pids[ 0 ] ];
- if( !Q_stricmp( cmd, "unmute" ) )
- {
- if( vic->client->pers.muted == qfalse )
- {
- ADMP( "^3!unmute: ^7player is not currently muted\n" );
- return qtrue;
- }
-
- vic->client->pers.muteExpires = 0;
- vic->client->pers.muted = qfalse;
-
- CPx( pids[ 0 ], "cp \"^1You have been unmuted\"" );
- AP( va( "print \"^3!unmute: ^7%s^7 has been unmuted by %s\n\"",
- vic->client->pers.netname,
- ( ent ) ? G_admin_adminPrintName( ent ) : "console" ) );
- } else {
- // Duration
- if( G_SayArgc() > 2 + skiparg )
- {
- G_SayArgv( 2 + skiparg, secs, sizeof( secs ) );
- seconds = G_admin_parse_time( secs );
- vic->client->pers.muteExpires = level.time + ( seconds * 1000 );
- }
-
- vic->client->pers.muted = qtrue;
-
- CPx( pids[ 0 ], "cp \"^1You've been muted\"" );
- AP( va( "print \"^3!mute: ^7%s^7 has been muted by ^7%s%s\n\"",
- vic->client->pers.netname,
- ( ent ) ? G_admin_adminPrintName( ent ) : "console",
- ( seconds ) ? va( " ^7for %i seconds", seconds ) : "" ) );
- }
-
- return qtrue;
-}
-
-qboolean G_admin_cp( gentity_t *ent, int skiparg )
-{
- int minargc;
- char *s;
-
- minargc = 2 + skiparg;
-
- if( G_SayArgc() < minargc )
- {
- ADMP( "^3!cp: ^7usage: !cp [message]\n" );
- return qfalse;
- }
-
- s = G_SayConcatArgs( 1 + skiparg );
- G_CP(ent);
- return qtrue;
-}
-
-qboolean G_admin_denybuild( gentity_t *ent, int skiparg )
-{
- int pids[ MAX_CLIENTS ];
- char name[ MAX_NAME_LENGTH ], err[ MAX_STRING_CHARS ];
- char command[ MAX_ADMIN_CMD_LEN ], *cmd;
- gentity_t *vic;
+ char name[ MAX_NAME_LENGTH ];
+ char command[ MAX_ADMIN_CMD_LEN ];
+ namelog_t *vic;
- G_SayArgv( skiparg, command, sizeof( command ) );
- cmd = command;
- if( cmd && *cmd == '!' )
- cmd++;
- if( G_SayArgc() < 2 + skiparg )
+ trap_Argv( 0, command, sizeof( command ) );
+ if( trap_Argc() < 2 )
{
- ADMP( va( "^3!%s: ^7usage: !%s [name|slot#]\n", cmd, cmd ) );
+ ADMP( va( "^3%s: ^7usage: %s [name|slot#]\n", command, command ) );
return qfalse;
}
- G_SayArgv( 1 + skiparg, name, sizeof( name ) );
- if( G_ClientNumbersFromString( name, pids ) != 1 )
+ trap_Argv( 1, name, sizeof( name ) );
+ if( !( vic = G_NamelogFromString( ent, name ) ) )
{
- G_MatchOnePlayer( pids, err, sizeof( err ) );
- ADMP( va( "^3!%s: ^7%s\n", cmd, err ) );
+ ADMP( va( "^3%s: ^7no match\n", command ) );
return qfalse;
}
- if( !admin_higher( ent, &g_entities[ pids[ 0 ] ] ) )
+ if( ent && !admin_higher_admin( ent->client->pers.admin,
+ G_admin_admin( vic->guid ) ) )
{
- ADMP( va( "^3!%s: ^7sorry, but your intended victim has a higher admin"
- " level than you\n", cmd ) );
+ ADMP( va( "^3%s: ^7sorry, but your intended victim has a higher admin"
+ " level than you\n", command ) );
return qfalse;
}
- vic = &g_entities[ pids[ 0 ] ];
- if( vic->client->pers.denyBuild )
+ if( vic->muted )
{
- if( !Q_stricmp( cmd, "denybuild" ) )
+ if( !Q_stricmp( command, "mute" ) )
{
- ADMP( "^3!denybuild: ^7player already has no building rights\n" );
- return qtrue;
+ ADMP( "^3mute: ^7player is already muted\n" );
+ return qfalse;
}
- vic->client->pers.denyBuild = qfalse;
- CPx( pids[ 0 ], "cp \"^1You've regained your building rights\"" );
- AP( va(
- "print \"^3!allowbuild: ^7building rights for ^7%s^7 restored by %s\n\"",
- vic->client->pers.netname,
- ( ent ) ? G_admin_adminPrintName( ent ) : "console" ) );
+ vic->muted = qfalse;
+ if( vic->slot > -1 )
+ CPx( vic->slot, "cp \"^1You have been unmuted\"" );
+ AP( va( "print \"^3unmute: ^7%s^7 has been unmuted by %s\n\"",
+ vic->name[ vic->nameOffset ],
+ ( ent ) ? ent->client->pers.netname : "console" ) );
}
else
{
- if( !Q_stricmp( cmd, "allowbuild" ) )
- {
- ADMP( "^3!allowbuild: ^7player already has building rights\n" );
- return qtrue;
- }
- vic->client->pers.denyBuild = qtrue;
- vic->client->ps.stats[ STAT_BUILDABLE ] = BA_NONE;
- if( vic->client->ps.stats[ STAT_PCLASS ]== PCL_ALIEN_BUILDER0 || vic->client->ps.stats[ STAT_PCLASS ] == PCL_ALIEN_BUILDER0_UPG )
+ if( !Q_stricmp( command, "unmute" ) )
{
- vic->suicideTime = level.time + 1000;
+ ADMP( "^3unmute: ^7player is not currently muted\n" );
+ return qfalse;
}
- CPx( pids[ 0 ], "cp \"^1You've lost your building rights\"" );
- AP( va(
- "print \"^3!denybuild: ^7building rights for ^7%s^7 revoked by ^7%s\n\"",
- vic->client->pers.netname,
- ( ent ) ? G_admin_adminPrintName( ent ) : "console" ) );
+ vic->muted = qtrue;
+ if( vic->slot > -1 )
+ CPx( vic->slot, "cp \"^1You've been muted\"" );
+ AP( va( "print \"^3mute: ^7%s^7 has been muted by ^7%s\n\"",
+ vic->name[ vic->nameOffset ],
+ ( ent ) ? ent->client->pers.netname : "console" ) );
}
+ admin_log( va( "%d (%s) \"%s" S_COLOR_WHITE "\"", vic->slot, vic->guid,
+ vic->name[ vic->nameOffset ] ) );
return qtrue;
}
-qboolean G_admin_denyweapon( gentity_t *ent, int skiparg )
+qboolean G_admin_denybuild( gentity_t *ent )
{
- int pids[ MAX_CLIENTS ];
- char name[ MAX_NAME_LENGTH ], err[ MAX_STRING_CHARS ];
- char command[ MAX_ADMIN_CMD_LEN ], *cmd;
- char buffer[ 32 ];
- int weapon = WP_NONE;
- int class = PCL_NONE;
- char *realname;
- gentity_t *vic;
- int flag;
- qboolean all = qfalse;
+ char name[ MAX_NAME_LENGTH ];
+ char command[ MAX_ADMIN_CMD_LEN ];
+ namelog_t *vic;
- G_SayArgv( skiparg, command, sizeof( command ) );
- cmd = command;
- if( cmd && *cmd == '!' )
- cmd++;
- if( G_SayArgc() < 3 + skiparg )
+ trap_Argv( 0, command, sizeof( command ) );
+ if( trap_Argc() < 2 )
{
- ADMP( va( "^3!%s: ^7usage: !%s [name|slot#] [class|weapon]\n", cmd, cmd ) );
+ ADMP( va( "^3%s: ^7usage: %s [name|slot#]\n", command, command ) );
return qfalse;
}
- G_SayArgv( 1 + skiparg, name, sizeof( name ) );
- if( G_ClientNumbersFromString( name, pids ) != 1 )
+ trap_Argv( 1, name, sizeof( name ) );
+ if( !( vic = G_NamelogFromString( ent, name ) ) )
{
- G_MatchOnePlayer( pids, err, sizeof( err ) );
- ADMP( va( "^3!%s: ^7%s\n", cmd, err ) );
+ ADMP( va( "^3%s: ^7no match\n", command ) );
return qfalse;
}
- if( !admin_higher( ent, &g_entities[ pids[ 0 ] ] ) )
+ if( ent && !admin_higher_admin( ent->client->pers.admin,
+ G_admin_admin( vic->guid ) ) )
{
- ADMP( va( "^3!%s: ^7sorry, but your intended victim has a higher admin"
- " level than you\n", cmd ) );
+ ADMP( va( "^3%s: ^7sorry, but your intended victim has a higher admin"
+ " level than you\n", command ) );
return qfalse;
}
- vic = &g_entities[ pids[ 0 ] ];
-
- if( vic == ent &&
- !Q_stricmp( cmd, "denyweapon" ) )
- {
- ADMP( va( "^3!%s: ^7sorry, you cannot %s yourself\n", cmd, cmd ) );
- return qfalse;
- }
-
- G_SayArgv( 2 + skiparg, buffer, sizeof( buffer ) );
-
- if( !Q_stricmp( buffer, "all" ) &&
- !Q_stricmp( cmd, "allowweapon" ) )
- {
- if( vic->client->pers.denyHumanWeapons ||
- vic->client->pers.denyAlienClasses )
- {
- vic->client->pers.denyHumanWeapons = 0;
- vic->client->pers.denyAlienClasses = 0;
-
- CPx( pids[ 0 ], "cp \"^1You've regained all weapon and class rights\"" );
- AP( va( "print \"^3!%s: ^7all weapon and class rights for ^7%s^7 restored by %s\n\"",
- cmd,
- vic->client->pers.netname,
- ( ent ) ? ent->client->pers.netname : "console" ) );
- }
- else
- {
- ADMP( va( "^3!%s: ^7player already has all rights\n", cmd ) );
- }
- return qtrue;
- }
-
- if( !Q_stricmp( buffer, "all" ) &&
- !Q_stricmp( cmd, "denyweapon" ) )
- {
- all = qtrue;
- weapon = WP_NONE;
- class = PCL_NONE;
-
- if( vic->client->pers.denyHumanWeapons == 0xFFFFFF &&
- vic->client->pers.denyAlienClasses == 0xFFFFFF )
- {
- ADMP( va( "^3!%s: ^7player already has no weapon or class rights\n", cmd ) );
- return qtrue;
- }
-
- if( vic->client->pers.teamSelection == PTE_HUMANS )
- {
- weapon = vic->client->ps.weapon;
- if( weapon < WP_PAIN_SAW || weapon > WP_GRENADE )
- weapon = WP_NONE;
- }
- if( vic->client->pers.teamSelection == PTE_ALIENS )
- {
- class = vic->client->pers.classSelection;
- if( class < PCL_ALIEN_LEVEL1 || class > PCL_ALIEN_LEVEL4 )
- class = PCL_NONE;
- }
-
- vic->client->pers.denyHumanWeapons = 0xFFFFFF;
- vic->client->pers.denyAlienClasses = 0xFFFFFF;
- }
- else
- {
- weapon = BG_FindWeaponNumForName( buffer );
- if( weapon < WP_PAIN_SAW || weapon > WP_GRENADE )
- class = BG_FindClassNumForName( buffer );
- if( ( weapon < WP_PAIN_SAW || weapon > WP_GRENADE ) &&
- ( class < PCL_ALIEN_LEVEL1 || class > PCL_ALIEN_LEVEL4 ) )
- {
- {
- ADMP( va( "^3!%s: ^7unknown weapon or class\n", cmd ) );
- return qfalse;
- }
- }
- }
-
- if( class == PCL_NONE )
+ if( vic->denyBuild )
{
- realname = BG_FindHumanNameForWeapon( weapon );
- flag = 1 << (weapon - WP_BLASTER);
- if( !Q_stricmp( cmd, "denyweapon" ) )
+ if( !Q_stricmp( command, "denybuild" ) )
{
- if( ( vic->client->pers.denyHumanWeapons & flag ) && !all )
- {
- ADMP( va( "^3!%s: ^7player already has no %s rights\n", cmd, realname ) );
- return qtrue;
- }
- vic->client->pers.denyHumanWeapons |= flag;
- if( vic->client->pers.teamSelection == PTE_HUMANS )
- {
- if( ( weapon == WP_GRENADE || all ) &&
- BG_InventoryContainsUpgrade( UP_GRENADE, vic->client->ps.stats ) )
- {
- BG_RemoveUpgradeFromInventory( UP_GRENADE, vic->client->ps.stats );
- G_AddCreditToClient( vic->client, (short)BG_FindPriceForUpgrade( UP_GRENADE ), qfalse );
- }
- if( BG_InventoryContainsWeapon( weapon, vic->client->ps.stats ) )
- {
- int maxAmmo, maxClips;
-
- BG_RemoveWeaponFromInventory( weapon, vic->client->ps.stats );
- G_AddCreditToClient( vic->client, (short)BG_FindPriceForWeapon( weapon ), qfalse );
-
- BG_AddWeaponToInventory( WP_MACHINEGUN, vic->client->ps.stats );
- BG_FindAmmoForWeapon( WP_MACHINEGUN, &maxAmmo, &maxClips );
- vic->client->ps.ammo = maxAmmo;
- vic->client->ps.clips = maxClips;
- G_ForceWeaponChange( vic, WP_MACHINEGUN );
- vic->client->ps.stats[ STAT_MISC ] = 0;
- ClientUserinfoChanged( pids[ 0 ], qfalse );
- }
- }
- }
- else
- {
- if( !( vic->client->pers.denyHumanWeapons & flag ) )
- {
- ADMP( va( "^3!%s: ^7player already has %s rights\n", cmd, realname ) );
- return qtrue;
- }
- vic->client->pers.denyHumanWeapons &= ~flag;
+ ADMP( "^3denybuild: ^7player already has no building rights\n" );
+ return qfalse;
}
+ vic->denyBuild = qfalse;
+ if( vic->slot > -1 )
+ CPx( vic->slot, "cp \"^1You've regained your building rights\"" );
+ AP( va(
+ "print \"^3allowbuild: ^7building rights for ^7%s^7 restored by %s\n\"",
+ vic->name[ vic->nameOffset ],
+ ( ent ) ? ent->client->pers.netname : "console" ) );
}
else
{
- realname = BG_FindHumanNameForClassNum( class );
- flag = 1 << class;
- if( !Q_stricmp( cmd, "denyweapon" ) )
+ if( !Q_stricmp( command, "allowbuild" ) )
{
- if( ( vic->client->pers.denyAlienClasses & flag ) && !all )
- {
- ADMP( va( "^3!%s: ^7player already has no %s rights\n", cmd, realname ) );
- return qtrue;
- }
- vic->client->pers.denyAlienClasses |= flag;
- if( vic->client->pers.teamSelection == PTE_ALIENS &&
- vic->client->pers.classSelection == class )
- {
- vec3_t infestOrigin;
- short cost;
-
- G_RoomForClassChange( vic, PCL_ALIEN_LEVEL0, infestOrigin );
-
- vic->client->pers.evolveHealthFraction = (float)vic->client->ps.stats[ STAT_HEALTH ] /
- (float)BG_FindHealthForClass( class );
- if( vic->client->pers.evolveHealthFraction < 0.0f )
- vic->client->pers.evolveHealthFraction = 0.0f;
- else if( vic->client->pers.evolveHealthFraction > 1.0f )
- vic->client->pers.evolveHealthFraction = 1.0f;
-
- vic->client->pers.classSelection = PCL_ALIEN_LEVEL0;
- cost = BG_ClassCanEvolveFromTo( PCL_ALIEN_LEVEL0, class, 9, 0 );
- if( cost < 0 ) cost = 0;
- G_AddCreditToClient( vic->client, cost, qfalse );
- ClientUserinfoChanged( pids[ 0 ], qfalse );
- VectorCopy( infestOrigin, vic->s.pos.trBase );
- ClientSpawn( vic, vic, vic->s.pos.trBase, vic->s.apos.trBase );
- }
+ ADMP( "^3allowbuild: ^7player already has building rights\n" );
+ return qfalse;
}
- else
+ vic->denyBuild = qtrue;
+ if( vic->slot > -1 )
{
- if( !( vic->client->pers.denyAlienClasses & flag ) )
- {
- ADMP( va( "^3!%s: ^7player already has %s rights\n", cmd, realname ) );
- return qtrue;
- }
- vic->client->pers.denyAlienClasses &= ~flag;
+ level.clients[ vic->slot ].ps.stats[ STAT_BUILDABLE ] = BA_NONE;
+ CPx( vic->slot, "cp \"^1You've lost your building rights\"" );
}
+ AP( va(
+ "print \"^3denybuild: ^7building rights for ^7%s^7 revoked by ^7%s\n\"",
+ vic->name[ vic->nameOffset ],
+ ( ent ) ? ent->client->pers.netname : "console" ) );
}
-
- if( all )
- realname = "weapon and class";
-
- CPx( pids[ 0 ], va( "cp \"^1You've %s your %s rights\"",
- ( !Q_stricmp( cmd, "denyweapon" ) ) ? "lost" : "regained",
- realname ) );
- AP( va(
- "print \"^3!%s: ^7%s rights for ^7%s^7 %s by %s\n\"",
- cmd, realname,
- vic->client->pers.netname,
- ( !Q_stricmp( cmd, "denyweapon" ) ) ? "revoked" : "restored",
- ( ent ) ? ent->client->pers.netname : "console" ) );
-
+ admin_log( va( "%d (%s) \"%s" S_COLOR_WHITE "\"", vic->slot, vic->guid,
+ vic->name[ vic->nameOffset ] ) );
return qtrue;
}
-qboolean G_admin_listadmins( gentity_t *ent, int skiparg )
+qboolean G_admin_listadmins( gentity_t *ent )
{
- int i, found = 0;
+ int i;
char search[ MAX_NAME_LENGTH ] = {""};
char s[ MAX_NAME_LENGTH ] = {""};
- int start = 0;
- qboolean numeric = qtrue;
- int drawn = 0;
- int minlevel = 1;
+ int start = MAX_CLIENTS;
- if( G_SayArgc() == 3 + skiparg )
+ if( trap_Argc() == 3 )
{
- G_SayArgv( 2 + skiparg, s, sizeof( s ) );
- if( s[ 0 ] >= '0' && s[ 0] <= '9' )
- {
- minlevel = atoi( s );
- if( minlevel < 1 )
- minlevel = 1;
- }
- }
-
- for( i = 0; i < MAX_ADMIN_ADMINS && g_admin_admins[ i ]; i++ )
- {
- if( g_admin_admins[ i ]->level >= minlevel )
- found++;
- }
- if( !found )
- {
- if( minlevel > 1 )
- {
- ADMP( va( "^3!listadmins: ^7no admins level %i or greater found\n", minlevel ) );
- }
- else
- {
- ADMP( "^3!listadmins: ^7no admins defined\n" );
- }
- return qfalse;
+ trap_Argv( 2, s, sizeof( s ) );
+ start = atoi( s );
}
-
- if( G_SayArgc() >= 2 + skiparg )
+ if( trap_Argc() > 1 )
{
- G_SayArgv( 1 + skiparg, s, sizeof( s ) );
- for( i = 0; i < sizeof( s ) && s[ i ]; i++ )
+ trap_Argv( 1, s, sizeof( s ) );
+ i = 0;
+ if( trap_Argc() == 2 )
{
- if( s[ i ] >= '0' && s[ i ] <= '9' )
- continue;
- numeric = qfalse;
+ i = s[ 0 ] == '-';
+ for( ; isdigit( s[ i ] ); i++ );
}
- if( numeric )
- {
+ if( i && !s[ i ] )
start = atoi( s );
- if( start > 0 )
- start -= 1;
- else if( start < 0 )
- start = found + start;
- }
else
G_SanitiseString( s, search, sizeof( search ) );
}
- if( start >= found || start < 0 )
- start = 0;
-
- drawn = admin_listadmins( ent, start, search, minlevel );
-
- if( search[ 0 ] )
- {
- if( drawn <= 20 )
- {
- ADMP( va( "^3!listadmins:^7 found %d admins level %i or greater matching '%s^7'\n",
- drawn, minlevel, search ) );
- }
- else
- {
- ADMP( va( "^3!listadmins:^7 found >20 admins level %i or greater matching '%s^7. Try a more narrow search.'\n",
- minlevel, search ) );
- }
- }
- else
- {
- ADMBP_begin();
- ADMBP( va( "^3!listadmins:^7 showing admins level %i or greater %d - %d of %d. ",
- minlevel,
- ( found ) ? ( start + 1 ) : 0,
- ( ( start + MAX_ADMIN_LISTITEMS ) > found ) ?
- found : ( start + MAX_ADMIN_LISTITEMS ),
- found ) );
- if( ( start + MAX_ADMIN_LISTITEMS ) < found )
- {
- if( minlevel > 1)
- {
- ADMBP( va( "run '!listadmins %d %d' to see more",
- ( start + MAX_ADMIN_LISTITEMS + 1 ), minlevel ) );
- }
- else
- {
- ADMBP( va( "run '!listadmins %d' to see more",
- ( start + MAX_ADMIN_LISTITEMS + 1 ) ) );
- }
- }
- ADMBP( "\n" );
- ADMBP_end();
- }
+ admin_listadmins( ent, start, search );
return qtrue;
}
-qboolean G_admin_listlayouts( gentity_t *ent, int skiparg )
+qboolean G_admin_listlayouts( gentity_t *ent )
{
char list[ MAX_CVAR_VALUE_STRING ];
char map[ MAX_QPATH ];
int count = 0;
char *s;
char layout[ MAX_QPATH ] = { "" };
- int i = 0;
-
- if( G_SayArgc( ) == 2 + skiparg )
- G_SayArgv( 1 +skiparg, map, sizeof( map ) );
+ size_t i = 0;
+
+ if( trap_Argc( ) == 2 )
+ trap_Argv( 1, map, sizeof( map ) );
else
trap_Cvar_VariableStringBuffer( "mapname", map, sizeof( map ) );
-
+
count = G_LayoutList( map, list, sizeof( list ) );
ADMBP_begin( );
- ADMBP( va( "^3!listlayouts:^7 %d layouts found for '%s':\n", count, map ) );
+ ADMBP( va( "^3listlayouts:^7 %d layouts found for '%s':\n", count, map ) );
s = &list[ 0 ];
while( *s )
{
@@ -4762,690 +2366,193 @@ qboolean G_admin_listlayouts( gentity_t *ent, int skiparg )
return qtrue;
}
-qboolean G_admin_listplayers( gentity_t *ent, int skiparg )
+qboolean G_admin_listplayers( gentity_t *ent )
{
- int i, j;
- int invisiblePlayers = 0;
- gclient_t *p;
- char c[ 3 ], t[ 2 ]; // color and team letter
- char n[ MAX_NAME_LENGTH ] = {""};
- char n2[ MAX_NAME_LENGTH ] = {""};
- char n3[ MAX_NAME_LENGTH ] = {""};
- char lname[ MAX_NAME_LENGTH ];
- char lname2[ MAX_NAME_LENGTH ];
- char muted[ 2 ], denied[ 2 ], dbuilder[ 2 ], immune[ 2 ], guidless[ 2 ];
- int l;
- char lname_fmt[ 5 ];
-
- //get amount of invisible players
- for( i = 0; i < level.maxclients; i++ ) {
- p = &level.clients[ i ];
- if ( p->sess.invisible == qtrue )
- invisiblePlayers++;
- }
+ int i, j;
+ gclient_t *p;
+ char c, t; // color and team letter
+ char *registeredname;
+ char lname[ MAX_NAME_LENGTH ];
+ char muted, denied;
+ int colorlen;
+ char namecleaned[ MAX_NAME_LENGTH ];
+ char name2cleaned[ MAX_NAME_LENGTH ];
+ g_admin_level_t *l;
+ g_admin_level_t *d = G_admin_level( 0 );
+ qboolean hint;
+ qboolean canset = G_admin_permission( ent, "setlevel" );
ADMBP_begin();
- ADMBP( va( "^3!listplayers^7: %d players connected:\n",
- level.numConnectedClients - invisiblePlayers ) );
+ ADMBP( va( "^3listplayers: ^7%d players connected:\n",
+ level.numConnectedClients ) );
for( i = 0; i < level.maxclients; i++ )
{
p = &level.clients[ i ];
-
- // Ignore invisible players
- if ( p->sess.invisible == qtrue )
+ if( p->pers.connected == CON_DISCONNECTED )
continue;
-
- Q_strncpyz( t, "S", sizeof( t ) );
- Q_strncpyz( c, S_COLOR_YELLOW, sizeof( c ) );
- if( p->pers.teamSelection == PTE_HUMANS )
- {
- Q_strncpyz( t, "H", sizeof( t ) );
- Q_strncpyz( c, S_COLOR_BLUE, sizeof( c ) );
- }
- else if( p->pers.teamSelection == PTE_ALIENS )
- {
- Q_strncpyz( t, "A", sizeof( t ) );
- Q_strncpyz( c, S_COLOR_RED, sizeof( c ) );
- }
-
if( p->pers.connected == CON_CONNECTING )
{
- Q_strncpyz( t, "C", sizeof( t ) );
- Q_strncpyz( c, S_COLOR_CYAN, sizeof( c ) );
+ t = 'C';
+ c = COLOR_YELLOW;
}
- else if( p->pers.connected != CON_CONNECTED )
+ else
{
- continue;
+ t = toupper( *( BG_TeamName( p->pers.teamSelection ) ) );
+ if( p->pers.teamSelection == TEAM_HUMANS )
+ c = COLOR_CYAN;
+ else if( p->pers.teamSelection == TEAM_ALIENS )
+ c = COLOR_RED;
+ else
+ c = COLOR_WHITE;
}
- guidless[ 0 ] = '\0';
- if( !Q_stricmp( p->pers.guid, "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" ) )
- {
- Q_strncpyz( guidless, "G", sizeof( guidless ) );
- }
- muted[ 0 ] = '\0';
- if( G_admin_permission( &g_entities[ i ], ADMF_NO_VOTE ) || G_admin_permission( &g_entities[ i ], ADMF_FAKE_NO_VOTE ) )
- {
- Q_strncpyz( muted, "V", sizeof( muted ) );
- }
- if( p->pers.muted )
- {
- Q_strncpyz( muted, "M", sizeof( muted ) );
- }
- denied[ 0 ] = '\0';
- if( p->pers.denyBuild )
- {
- Q_strncpyz( denied, "B", sizeof( denied ) );
- }
- if( p->pers.denyHumanWeapons || p->pers.denyAlienClasses )
- {
- Q_strncpyz( denied, "W", sizeof( denied ) );
- }
+ muted = p->pers.namelog->muted ? 'M' : ' ';
+ denied = p->pers.namelog->denyBuild ? 'B' : ' ';
- dbuilder[ 0 ] = '\0';
- if( p->pers.designatedBuilder )
+ l = d;
+ registeredname = NULL;
+ hint = canset;
+ if( p->pers.admin )
{
- if( !G_admin_permission( &g_entities[ i ], ADMF_INCOGNITO ) &&
- G_admin_permission( &g_entities[ i ], ADMF_DBUILDER ) &&
- G_admin_permission(ent, ADMF_SEESFULLLISTPLAYERS ) )
- {
- Q_strncpyz( dbuilder, "P", sizeof( dbuilder ) );
- }
- else
+ if( hint )
+ hint = admin_higher( ent, &g_entities[ i ] );
+ if( hint || !G_admin_permission( &g_entities[ i ], ADMF_INCOGNITO ) )
{
- Q_strncpyz( dbuilder, "D", sizeof( dbuilder ) );
+ l = G_admin_level( p->pers.admin->level );
+ G_SanitiseString( p->pers.netname, namecleaned,
+ sizeof( namecleaned ) );
+ G_SanitiseString( p->pers.admin->name,
+ name2cleaned, sizeof( name2cleaned ) );
+ if( Q_stricmp( namecleaned, name2cleaned ) )
+ registeredname = p->pers.admin->name;
}
}
- immune[ 0 ] = '\0';
- if( G_admin_permission( &g_entities[ i ], ADMF_BAN_IMMUNITY ) &&
- G_admin_permission(ent, ADMF_SEESFULLLISTPLAYERS ) )
- {
- Q_strncpyz( immune, "I", sizeof( immune ) );
- }
- if( p->pers.paused )
- {
- // use immunity slot for paused player status
- Q_strncpyz( immune, "L", sizeof( immune ) );
- }
+ if( l )
+ Q_strncpyz( lname, l->name, sizeof( lname ) );
- l = 0;
- G_SanitiseString( p->pers.netname, n2, sizeof( n2 ) );
- n[ 0 ] = '\0';
- for( j = 0; j < MAX_ADMIN_ADMINS && g_admin_admins[ j ]; j++ )
+ for( colorlen = j = 0; lname[ j ]; j++ )
{
- if( !Q_stricmp( g_admin_admins[ j ]->guid, p->pers.guid ) )
- {
-
- // don't gather aka or level info if the admin is incognito
- if( ent && G_admin_permission( &g_entities[ i ], ADMF_INCOGNITO ) && !G_admin_permission(ent, ADMF_SEESINCOGNITO) )
- {
- break;
- }
- l = g_admin_admins[ j ]->level;
- G_SanitiseString( g_admin_admins[ j ]->name, n3, sizeof( n3 ) );
- if( Q_stricmp( n2, n3 ) )
- {
- Q_strncpyz( n, g_admin_admins[ j ]->name, sizeof( n ) );
- }
- break;
- }
+ if( Q_IsColorString( &lname[ j ] ) )
+ colorlen += 2;
}
- lname[ 0 ] = '\0';
- Q_strncpyz( lname_fmt, "%s", sizeof( lname_fmt ) );
- for( j = 0; j < MAX_ADMIN_LEVELS && g_admin_levels[ j ]; j++ )
- {
- if( g_admin_levels[ j ]->level == l )
- {
- Q_strncpyz( lname, g_admin_levels[ j ]->name, sizeof( lname ) );
- if( *lname )
- {
- G_DecolorString( lname, lname2 );
- Com_sprintf( lname_fmt, sizeof( lname_fmt ), "%%%is",
- ( admin_level_maxname + (int)( strlen( lname ) - strlen( lname2 ) ) ) );
- Com_sprintf( lname2, sizeof( lname2 ), lname_fmt, lname );
- }
- break;
- }
- }
+ ADMBP( va( "%2i ^%c%c %s %s^7 %*s^7 ^1%c%c^7 %s^7 %s%s%s\n",
+ i,
+ c,
+ t,
+ p->pers.guidless ? "^1---" : va( "^7%-2i^2%c", l ? l->level : 0, hint ? '*' : ' ' ),
+ p->pers.alternateProtocol == 2 ? "^11" : p->pers.alternateProtocol == 1 ? "^3G" : " ",
+ admin_level_maxname + colorlen,
+ lname,
+ muted,
+ denied,
+ p->pers.netname,
+ ( registeredname ) ? "(a.k.a. " : "",
+ ( registeredname ) ? registeredname : "",
+ ( registeredname ) ? S_COLOR_WHITE ")" : "" ) );
- if ( G_admin_permission(ent, ADMF_SEESFULLLISTPLAYERS ) ) {
- ADMBP( va( "%2i %s%s^7 %-2i %s^7 ^1%1s%1s%1s%1s%1s^7 %s^7 %s%s^7%s\n",
- i,
- c,
- t,
- l,
- ( *lname ) ? lname2 : "",
- immune,
- muted,
- dbuilder,
- denied,
- guidless,
- p->pers.netname,
- ( *n ) ? "(a.k.a. " : "",
- n,
- ( *n ) ? ")" : ""
- ) );
- } else {
- ADMBP( va( "%2i %s%s^7 %-2i %s^7 ^1%1s%1s%1s%1s^7 %s^7 %s%s^7%s\n",
- i,
- c,
- t,
- l,
- ( *lname ) ? lname2 : "",
- immune,
- muted,
- dbuilder,
- denied,
- p->pers.netname,
- ( *n ) ? "(a.k.a. " : "",
- n,
- ( *n ) ? ")" : ""
- ) );
- }
}
ADMBP_end();
return qtrue;
}
-#define MAX_LISTMAPS_MAPS 256
-
-static int SortMaps(const void *a, const void *b)
+static qboolean ban_matchip( void *ban, const void *ip )
{
- return strcmp(*(char **)a, *(char **)b);
+ return G_AddressCompare( &((g_admin_ban_t *)ban)->ip, (addr_t *)ip ) ||
+ G_AddressCompare( (addr_t *)ip, &((g_admin_ban_t *)ban)->ip );
}
-
-qboolean G_admin_listmaps( gentity_t *ent, int skiparg )
+static qboolean ban_matchname( void *ban, const void *name )
{
- char fileList[ 4096 ] = {""};
- char *fileSort[ MAX_LISTMAPS_MAPS ];
- char search[ 16 ] = {""};
- int numFiles;
- int i;
- int fileLen = 0;
- int count = 0;
- char *filePtr;
- int rows;
+ char match[ MAX_NAME_LENGTH ];
- if( G_SayArgc( ) > 1 + skiparg )
- {
- G_SayArgv( skiparg + 1, search, sizeof( search ) );
- }
-
- numFiles = trap_FS_GetFileList( "maps/", ".bsp",
- fileList, sizeof( fileList ) );
- filePtr = fileList;
- for( i = 0; i < numFiles && count < MAX_LISTMAPS_MAPS; i++, filePtr += fileLen + 1 )
- {
- fileLen = strlen( filePtr );
- if (fileLen < 5)
- continue;
-
- filePtr[ fileLen - 4 ] = '\0';
-
- if( search[ 0 ] && !strstr( filePtr, search ) )
- continue;
-
- fileSort[ count ] = filePtr;
- count++;
- }
-
- qsort(fileSort, count, sizeof(fileSort[ 0 ]), SortMaps);
-
- rows = count / 3;
- if ( rows * 3 < count ) rows++;
-
- ADMBP_begin();
- for( i = 0; i < rows; i++ )
- {
- ADMBP( va( "^7%20s %20s %20s\n",
- fileSort[ i ],
- ( rows + i < count ) ? fileSort[ rows + i ] : "",
- ( rows * 2 + i < count ) ? fileSort[ rows * 2 + i ] : "" ) );
- }
- if ( search[ 0 ] )
- ADMBP( va( "^3!listmaps: ^7found %d maps matching '%s^7'.\n", count, search ) );
- else
- ADMBP( va( "^3!listmaps: ^7listing %d maps.\n", count ) );
-
- ADMBP_end();
-
- return qtrue;
+ G_SanitiseString( ( (g_admin_ban_t *)ban )->name, match, sizeof( match ) );
+ return strstr( match, (const char *)name ) != NULL;
}
-
-qboolean G_admin_listrotation( gentity_t *ent, int skiparg )
+static void ban_out( void *ban, char *str )
{
- int i, j, statusColor;
- char mapnames[ MAX_STRING_CHARS ];
- char *status = NULL;
-
- extern mapRotations_t mapRotations;
+ size_t i;
+ int colorlen1 = 0;
+ char duration[ MAX_DURATION_LENGTH ];
+ char *d_color = S_COLOR_WHITE;
+ char date[ 11 ];
+ g_admin_ban_t *b = ( g_admin_ban_t * )ban;
+ int t = trap_RealTime( NULL );
+ char *made = b->made;
- // Check for an active map rotation
- if ( !G_MapRotationActive() ||
- g_currentMapRotation.integer == NOT_ROTATING )
+ for( i = 0; b->name[ i ]; i++ )
{
- trap_SendServerCommand( ent-g_entities, "print \"^3!rotation: ^7There is no active map rotation on this server\n\"" );
- return qfalse;
+ if( Q_IsColorString( &b->name[ i ] ) )
+ colorlen1 += 2;
}
- // Locate the active map rotation and output its contents
- for( i = 0; i < mapRotations.numRotations; i++ )
- {
- if ( i == g_currentMapRotation.integer )
- {
- int currentMap = G_GetCurrentMap( i );
-
- ADMBP_begin();
- ADMBP( va( "^3!rotation: ^7%s\n", mapRotations.rotations[ i ].name ) );
-
- for( j = 0; j < mapRotations.rotations[ i ].numMaps; j++ )
- {
- Q_strncpyz( mapnames, mapRotations.rotations[ i ].maps[ j ].name, sizeof( mapnames ) );
-
- if( !Q_stricmp( mapRotations.rotations[ i ].maps[ j ].name, "*VOTE*" ) )
- {
- char slotMap[ 64 ];
- int lineLen = 0;
- int k;
-
- trap_Cvar_VariableStringBuffer( "mapname", slotMap, sizeof( slotMap ) );
- mapnames[ 0 ] = '\0';
- for( k = 0; k < mapRotations.rotations[ i ].maps[ j ].numConditions; k++ )
- {
- char *thisMap;
- int mc = 7;
-
- if( mapRotations.rotations[ i ].maps[ j ].conditions[ k ].lhs != MCV_VOTE )
- continue;
-
- thisMap = mapRotations.rotations[ i ].maps[ j ].conditions[ k ].dest;
- lineLen += strlen( thisMap ) + 1;
-
- if( currentMap == j && !Q_stricmp( thisMap, slotMap ) )
- mc = 3;
- Q_strcat( mapnames, sizeof( mapnames ), va( "^7%s%s^%i%s",
- ( k ) ? ", " : "",
- ( lineLen > 50 ) ? "\n " : "",
- mc, thisMap ) );
- if( lineLen > 50 )
- lineLen = strlen( thisMap ) + 2;
- else
- lineLen++;
- }
-
- if( currentMap == j )
- {
- statusColor = 3;
- status = "current slot";
- }
- else if( !k )
- {
- statusColor = 1;
- status = "empty vote";
- }
- else
- {
- statusColor = 7;
- status = "vote";
- }
- } else if( !Q_stricmp( mapRotations.rotations[ i ].maps[ j ].name, "*RANDOM*" ) )
- {
- char slotMap[ 64 ];
- int lineLen = 0;
- int k;
-
- trap_Cvar_VariableStringBuffer( "mapname", slotMap, sizeof( slotMap ) );
- mapnames[ 0 ] = '\0';
- for( k = 0; k < mapRotations.rotations[ i ].maps[ j ].numConditions; k++ )
- {
- char *thisMap;
- int mc = 7;
-
- if( mapRotations.rotations[ i ].maps[ j ].conditions[ k ].lhs != MCV_SELECTEDRANDOM )
- continue;
-
- thisMap = mapRotations.rotations[ i ].maps[ j ].conditions[ k ].dest;
- lineLen += strlen( thisMap ) + 1;
-
- if( currentMap == j && !Q_stricmp( thisMap, slotMap ) )
- mc = 3;
- Q_strcat( mapnames, sizeof( mapnames ), va( "^7%s%s^%i%s",
- ( k ) ? ", " : "",
- ( lineLen > 50 ) ? "\n " : "",
- mc, thisMap ) );
- if( lineLen > 50 )
- lineLen = strlen( thisMap ) + 2;
- else
- lineLen++;
- }
-
- if( currentMap == j )
- {
- statusColor = 3;
- status = "current slot";
- }
- else if( !k )
- {
- statusColor = 1;
- status = "empty Random";
- }
- else
- {
- statusColor = 7;
- status = "Random";
- }
- }
- else if ( currentMap == j )
- {
- statusColor = 3;
- status = "current slot";
- }
- else if ( !G_MapExists( mapRotations.rotations[ i ].maps[ j ].name ) )
- {
- statusColor = 1;
- status = "missing";
- }
- else
- {
- statusColor = 7;
- status = "";
- }
- ADMBP( va( " ^%i%-12s %3i %s\n", statusColor, status, j + 1, mapnames ) );
- }
-
- ADMBP_end();
-
- // No maps were found in the active map rotation
- if ( mapRotations.rotations[ i ].numMaps < 1 )
- {
- trap_SendServerCommand( ent-g_entities, "print \" - ^7Empty!\n\"" );
- return qfalse;
- }
- }
- }
+ // only print out the the date part of made
+ date[ 0 ] = '\0';
+ for( i = 0; *made && *made != ' ' && i < sizeof( date ) - 1; i++ )
+ date[ i ] = *made++;
+ date[ i ] = 0;
- if( g_nextMap.string[0] )
+ if( !b->expires || b->expires - t > 0 )
+ G_admin_duration( b->expires ? b->expires - t : - 1,
+ duration, sizeof( duration ) );
+ else
{
- ADMP( va ("^5 Next map overriden by g_nextMap to: %s\n", g_nextMap.string ) );
+ Q_strncpyz( duration, "expired", sizeof( duration ) );
+ d_color = S_COLOR_CYAN;
}
-
- return qtrue;
-}
-
-qboolean G_admin_showbans( gentity_t *ent, int skiparg )
+ Com_sprintf( str, MAX_STRING_CHARS, "%-*s %s%-15s " S_COLOR_WHITE "%-8s %s"
+ "\n \\__ %s%-*s " S_COLOR_WHITE "%s",
+ MAX_NAME_LENGTH + colorlen1 - 1, b->name,
+ ( strchr( b->ip.str, '/' ) ) ? S_COLOR_RED : S_COLOR_WHITE,
+ b->ip.str,
+ date,
+ b->banner,
+ d_color,
+ MAX_DURATION_LENGTH - 1,
+ duration,
+ b->reason );
+}
+qboolean G_admin_showbans( gentity_t *ent )
{
- int i, found = 0;
- int t;
- char duration[ 32 ];
- char sduration[ 32 ];
- char suspended[ 64 ] = { "" };
- char name_fmt[ 32 ] = { "%s" };
- char banner_fmt[ 32 ] = { "%s" };
- int max_name = 1, max_banner = 1;
- int secs;
- int start = 0;
+ int i;
+ int start = 1;
char filter[ MAX_NAME_LENGTH ] = {""};
- char date[ 11 ];
- char *made;
- int j;
- char n1[ MAX_NAME_LENGTH * 2 ] = {""};
- char n2[ MAX_NAME_LENGTH * 2 ] = {""};
- int bannerslevel = 0;
- qboolean numeric = qtrue;
- char *ip_match = NULL;
- int ip_match_len = 0;
char name_match[ MAX_NAME_LENGTH ] = {""};
- int show_count = 0;
- qboolean subnetfilter = qfalse;
+ qboolean ipmatch = qfalse;
+ addr_t ip;
- t = trap_RealTime( NULL );
-
- for( i = 0; i < MAX_ADMIN_BANS && g_admin_bans[ i ]; i++ )
+ if( trap_Argc() == 3 )
{
- if( g_admin_bans[ i ]->expires != 0
- && ( g_admin_bans[ i ]->expires - t ) < 1 )
- {
- continue;
- }
- found++;
+ trap_Argv( 2, filter, sizeof( filter ) );
+ start = atoi( filter );
}
-
- if( G_SayArgc() >= 2 + skiparg )
+ if( trap_Argc() > 1 )
{
- G_SayArgv( 1 + skiparg, filter, sizeof( filter ) );
- if( G_SayArgc() >= 3 + skiparg )
- {
+ trap_Argv( 1, filter, sizeof( filter ) );
+ i = 0;
+ if( trap_Argc() == 2 )
+ for( i = filter[ 0 ] == '-'; isdigit( filter[ i ] ); i++ );
+ if( !filter[ i ] )
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!showbans: ^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';
- }
- // showbans 1 means start with ban 0
- if( start > 0 )
- start -= 1;
- else if( start < 0 )
- start = found + start;
- }
-
- if( start >= MAX_ADMIN_BANS || start < 0 )
- start = 0;
-
- for( i = start; i < MAX_ADMIN_BANS && g_admin_bans[ i ]
- && show_count < MAX_ADMIN_SHOWBANS; i++ )
- {
- qboolean match = qfalse;
-
- if (!numeric)
- {
- if( !subnetfilter )
- {
- G_SanitiseString( g_admin_bans[ i ]->name, n1, sizeof( n1 ) );
- if (strstr( n1, name_match) )
- match = qtrue;
- }
- else
- {
- int mask = -1;
- int dummy;
- int scanflen = 0;
- scanflen = sscanf( g_admin_bans[ i ]->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, g_admin_bans[ i ]->ip, ip_match_len) == 0 )
- {
- G_DecolorString( g_admin_bans[ i ]->name, n1 );
- G_DecolorString( g_admin_bans[ i ]->banner, n2 );
- if( strlen( n1 ) > max_name )
- {
- max_name = strlen( n1 );
- }
- if( strlen( n2 ) > max_banner )
- max_banner = strlen( n2 );
-
- show_count++;
- }
+ else if( !( ipmatch = G_AddressParse( filter, &ip ) ) )
+ G_SanitiseString( filter, name_match, sizeof( name_match ) );
}
- if( start >= found )
- {
- ADMP( va( "^3!showbans: ^7there are %d active bans\n", found ) );
- return qfalse;
- }
- ADMBP_begin();
- show_count = 0;
- for( i = start; i < MAX_ADMIN_BANS && g_admin_bans[ i ]
- && show_count < MAX_ADMIN_SHOWBANS; i++ )
- {
- if (!numeric)
- {
- if( !subnetfilter )
- {
- G_SanitiseString( g_admin_bans[ i ]->name, n1, sizeof( n1 ) );
- if ( strstr ( n1, name_match ) == NULL )
- continue;
- }
- else
- {
- int mask = -1;
- int dummy;
- int scanflen = 0;
- scanflen = sscanf( g_admin_bans[ i ]->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, g_admin_bans[ i ]->ip, ip_match_len ) != 0)
- continue;
-
- // only print out the the date part of made
- date[ 0 ] = '\0';
- made = g_admin_bans[ i ]->made;
- for( j = 0; made && *made; j++ )
- {
- if( ( j + 1 ) >= sizeof( date ) )
- break;
- if( *made == ' ' )
- break;
- date[ j ] = *made;
- date[ j + 1 ] = '\0';
- made++;
- }
-
- if( g_admin_bans[ i ]->expires != 0
- && ( g_admin_bans[ i ]->expires - t ) < 1 )
- {
- Com_sprintf( duration, sizeof( duration ), "^1*EXPIRED*^7" );
- } else {
- secs = ( g_admin_bans[ i ]->expires - t );
- G_admin_duration( secs, duration, sizeof( duration ) );
- }
-
- suspended[ 0 ] = '\0';
- if( g_admin_bans[ i ]->suspend > t )
- {
- G_admin_duration( g_admin_bans[ i ]->suspend - t, sduration, sizeof( sduration ) );
- Com_sprintf( suspended, sizeof( suspended ), "^3*SUSPENDED*^7 for %s^7",
- sduration );
- }
-
- G_DecolorString( g_admin_bans[ i ]->name, n1 );
- Com_sprintf( name_fmt, sizeof( name_fmt ), "%%%is",
- ( max_name + strlen( g_admin_bans[ i ]->name ) - strlen( n1 ) ) );
- Com_sprintf( n1, sizeof( n1 ), name_fmt, g_admin_bans[ i ]->name );
-
- G_DecolorString( g_admin_bans[ i ]->banner, n2 );
- Com_sprintf( banner_fmt, sizeof( banner_fmt ), "%%%is",
- ( max_banner + strlen( g_admin_bans[ i ]->banner ) - strlen( n2 ) ) );
- Com_sprintf( n2, sizeof( n2 ), banner_fmt, g_admin_bans[ i ]->banner );
- bannerslevel = g_admin_bans[ i ]->bannerlevel;
-
- ADMBP( va( "%4i %s^7 %-15s %-8s %-10s\n | %-15s^7 Level:%2i\n | %s\n \\__ %s\n",
- ( i + 1 ),
- n1,
- g_admin_bans[ i ]->ip,
- date,
- duration,
- n2,
- bannerslevel,
- suspended,
- g_admin_bans[ i ]->reason ) );
-
- 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!showbans:^7 found %d matching bans by %s. ",
- show_count,
- matchmethod ) );
- }
- else
- {
- ADMBP( va( "^3!showbans:^7 showing bans %d - %d of %d. ",
- ( found ) ? ( start + 1 ) : 0,
- ( ( start + MAX_ADMIN_SHOWBANS ) > found ) ?
- found : ( start + MAX_ADMIN_SHOWBANS ),
- found ) );
- }
-
- if( ( start + MAX_ADMIN_SHOWBANS ) < found )
- {
- ADMBP( va( "run !showbans %d %s to see more",
- ( start + MAX_ADMIN_SHOWBANS + 1 ),
- (filter[0]) ? filter : "" ) );
- }
- ADMBP( "\n" );
- ADMBP_end();
+ admin_search( ent, "showbans", "bans",
+ ipmatch ? ban_matchip : ban_matchname,
+ ban_out, g_admin_bans,
+ ipmatch ? (void * )&ip : (void *)name_match,
+ start, 1, MAX_ADMIN_SHOWBANS );
return qtrue;
}
-qboolean G_admin_help( gentity_t *ent, int skiparg )
+qboolean G_admin_adminhelp( gentity_t *ent )
{
- int i;
- int commandsPerLine = 6;
-
- if( G_SayArgc() < 2 + skiparg )
+ g_admin_command_t *c;
+ if( trap_Argc() < 2 )
{
- int j = 0;
+ size_t i;
int count = 0;
ADMBP_begin();
@@ -5453,235 +2560,104 @@ qboolean G_admin_help( gentity_t *ent, int skiparg )
{
if( G_admin_permission( ent, g_admin_cmds[ i ].flag ) )
{
- ADMBP( va( "^3!%-12s", g_admin_cmds[ i ].keyword ) );
- j++;
+ ADMBP( va( "^3%-12s", g_admin_cmds[ i ].keyword ) );
count++;
- }
- // show 6 commands per line
- if( j == 6 )
- {
- ADMBP( "\n" );
- j = 0;
+ // show 6 commands per line
+ if( count % 6 == 0 )
+ ADMBP( "\n" );
}
}
- for( i = 0; i < MAX_ADMIN_COMMANDS && g_admin_commands[ i ]; i++ )
+ for( c = g_admin_commands; c; c = c->next )
{
- if( !G_admin_permission( ent, g_admin_commands[ i ]->flag ) )
+ if( !G_admin_permission( ent, c->flag ) )
continue;
- ADMBP( va( "^3!%-12s", g_admin_commands[ i ]->command ) );
- j++;
+ ADMBP( va( "^3%-12s", c->command ) );
count++;
// show 6 commands per line
- if( j == 6 )
- {
+ if( count % 6 == 0 )
ADMBP( "\n" );
- j = 0;
- }
}
-
- if( count )
+ if( count % 6 )
ADMBP( "\n" );
- ADMBP( va( "^3!help: ^7%i available commands\n", count ) );
- ADMBP( "run !help [^3command^7] for help with a specific command.\n" );
- ADMBP( "The following non-standard /commands may also be available to you: \n" );
- count = 1;
-
- if( ent && g_AllStats.integer ) {
- if( count > commandsPerLine && ( count % commandsPerLine ) == 1 ) ADMBP( "\n" );
- ADMBP( va( "^5/%-12s", "allstats" ) );
- count++;
- }
- if ( ent ) {
- if( count > commandsPerLine && ( count % commandsPerLine ) == 1 ) ADMBP( "\n" );
- ADMBP( va( "^5/%-12s", "builder" ) );
- count++;
- }
- if( ent && g_allowVote.integer && G_admin_permission( ent, ADMF_NO_VOTE ) ) {
- if( count > commandsPerLine && ( count % commandsPerLine ) == 1 ) ADMBP( "\n" );
- ADMBP( va( "^5/%-12s", "callvote" ) );
- count++;
- }
- if( ent && g_allowVote.integer && G_admin_permission( ent, ADMF_NO_VOTE ) && ( ent->client->ps.stats[ STAT_PTEAM ] == PTE_ALIENS || ent->client->ps.stats[ STAT_PTEAM ] == PTE_HUMANS ) ) {
- if( count > commandsPerLine && ( count % commandsPerLine ) == 1 ) ADMBP( "\n" );
- ADMBP( va( "^5/%-12s", "callteamvote" ) );
- count++;
- }
- if( ent && g_allowShare.integer && ( ent->client->ps.stats[ STAT_PTEAM ] == PTE_ALIENS || ent->client->ps.stats[ STAT_PTEAM ] == PTE_HUMANS ) ) {
- if( count > commandsPerLine && ( count % commandsPerLine ) == 1 ) ADMBP( "\n" );
- ADMBP( va( "^5/%-12s", "donate" ) );
- count++;
- }
- if( g_privateMessages.integer ) {
- if( count > commandsPerLine && ( count % commandsPerLine ) == 1 ) ADMBP( "\n" );
- ADMBP( va( "^5/%-12s", "m" ) );
- count++;
- }
- if( ent && g_markDeconstruct.integer == 2 && ( ent->client->ps.stats[ STAT_PTEAM ] == PTE_ALIENS || ent->client->ps.stats[ STAT_PTEAM ] == PTE_HUMANS ) ) {
- if( count > commandsPerLine && ( count % commandsPerLine ) == 1 ) ADMBP( "\n" );
- ADMBP( va( "^5/%-12s", "mark" ) );
- count++;
- }
- if( ent && g_actionPrefix.string[0] ) {
- if( count > commandsPerLine && ( count % commandsPerLine ) == 1 ) ADMBP( "\n" );
- ADMBP( va( "^5/%-12s", "me" ) );
- count++;
- }
- if( ent && g_actionPrefix.string[0] ) {
- if( count > commandsPerLine && ( count % commandsPerLine ) == 1 ) ADMBP( "\n" );
- ADMBP( va( "^5/%-12s", "me_team" ) );
- count++;
- }
- if( ent && g_actionPrefix.string[0] && ( ent->client->ps.stats[ STAT_PTEAM ] == PTE_ALIENS || ent->client->ps.stats[ STAT_PTEAM ] == PTE_HUMANS ) ) {
- if( count > commandsPerLine && ( count % commandsPerLine ) == 1 ) ADMBP( "\n" );
- ADMBP( va( "^5/%-12s", "mt" ) );
- count++;
- }
- if( ent && g_myStats.integer && ( ent->client->ps.stats[ STAT_PTEAM ] == PTE_ALIENS || ent->client->ps.stats[ STAT_PTEAM ] == PTE_HUMANS ) ) {
- if( count > commandsPerLine && ( count % commandsPerLine ) == 1 ) ADMBP( "\n" );
- ADMBP( va( "^5/%-12s", "mystats" ) );
- count++;
- }
- if( ent && ent->client->pers.designatedBuilder && ( ent->client->ps.stats[ STAT_PTEAM ] == PTE_ALIENS || ent->client->ps.stats[ STAT_PTEAM ] == PTE_HUMANS ) ) {
- if( count > commandsPerLine && ( count % commandsPerLine ) == 1 ) ADMBP( "\n" );
- ADMBP( va( "^5/%-12s", "protect" ) );
- count++;
- }
- if( ent && ent->client->pers.designatedBuilder && ( ent->client->ps.stats[ STAT_PTEAM ] == PTE_ALIENS || ent->client->ps.stats[ STAT_PTEAM ] == PTE_HUMANS ) ) {
- if( count > commandsPerLine && ( count % commandsPerLine ) == 1 ) ADMBP( "\n" );
- ADMBP( va( "^5/%-12s", "resign" ) );
- count++;
- }
- if( g_publicSayadmins.integer || G_admin_permission( ent, ADMF_ADMINCHAT ) ) {
- if( count > commandsPerLine && ( count % commandsPerLine ) == 1 ) ADMBP( "\n" );
- ADMBP( va( "^5/%-12s", "say_admins" ) );
- count++;
- }
- if( ent && ( ent->client->ps.stats[ STAT_PTEAM ] == PTE_ALIENS || ent->client->ps.stats[ STAT_PTEAM ] == PTE_HUMANS ) ) {
- if( count > commandsPerLine && ( count % commandsPerLine ) == 1 ) ADMBP( "\n" );
- ADMBP( va( "^5/%-12s", "say_area" ) );
- count++;
- }
- if( ent && g_allowShare.integer && ( ent->client->ps.stats[ STAT_PTEAM ] == PTE_ALIENS || ent->client->ps.stats[ STAT_PTEAM ] == PTE_HUMANS ) ) {
- if( count > commandsPerLine && ( count % commandsPerLine ) == 1 ) ADMBP( "\n" );
- ADMBP( va( "^5/%-12s", "share" ) );
- count++;
- }
- if( ent && g_teamStatus.integer && ( ent->client->ps.stats[ STAT_PTEAM ] == PTE_ALIENS || ent->client->ps.stats[ STAT_PTEAM ] == PTE_HUMANS ) ) {
- if( count > commandsPerLine && ( count % commandsPerLine ) == 1 ) ADMBP( "\n" );
- ADMBP( va( "^5/%-12s", "teamstatus" ) );
- count++;
- }
- ADMBP( "\n" );
+ ADMBP( va( "^3adminhelp: ^7%i available commands\n", count ) );
+ ADMBP( "run adminhelp [^3command^7] for adminhelp with a specific command.\n" );
ADMBP_end();
return qtrue;
}
else
{
- //!help param
+ // adminhelp param
char param[ MAX_ADMIN_CMD_LEN ];
- char *cmd;
+ g_admin_cmd_t *admincmd;
+ qboolean denied = qfalse;
- G_SayArgv( 1 + skiparg, param, sizeof( param ) );
- cmd = ( param[0] == '!' ) ? &param[1] : &param[0];
+ trap_Argv( 1, param, sizeof( param ) );
ADMBP_begin();
- for( i = 0; i < adminNumCmds; i++ )
+ if( ( c = G_admin_command( param ) ) )
{
- if( !Q_stricmp( cmd, g_admin_cmds[ i ].keyword ) )
+ if( G_admin_permission( ent, c->flag ) )
{
- if( !G_admin_permission( ent, g_admin_cmds[ i ].flag ) )
- {
- ADMBP( va( "^3!help: ^7you have no permission to use '%s'\n",
- g_admin_cmds[ i ].keyword ) );
- ADMBP_end();
- return qfalse;
- }
- ADMBP( va( "^3!help: ^7help for '!%s':\n",
- g_admin_cmds[ i ].keyword ) );
- ADMBP( va( " ^3Function: ^7%s\n", g_admin_cmds[ i ].function ) );
- ADMBP( va( " ^3Syntax: ^7!%s %s\n", g_admin_cmds[ i ].keyword,
- g_admin_cmds[ i ].syntax ) );
- ADMBP( va( " ^3Flag: ^7'%s'\n", g_admin_cmds[ i ].flag ) );
- ADMBP_end();
+ ADMBP( va( "^3adminhelp: ^7help for '%s':\n", c->command ) );
+ ADMBP( va( " ^3Description: ^7%s\n", c->desc ) );
+ ADMBP( va( " ^3Syntax: ^7%s\n", c->command ) );
+ ADMBP( va( " ^3Flag: ^7'%s'\n", c->flag ) );
+ ADMBP_end( );
return qtrue;
}
+ denied = qtrue;
}
- for( i = 0; i < MAX_ADMIN_COMMANDS && g_admin_commands[ i ]; i++ )
+ if( ( admincmd = G_admin_cmd( param ) ) )
{
- if( !Q_stricmp( cmd, g_admin_commands[ i ]->command ) )
+ if( G_admin_permission( ent, admincmd->flag ) )
{
- if( !G_admin_permission( ent, g_admin_commands[ i ]->flag ) )
- {
- ADMBP( va( "^3!help: ^7you have no permission to use '%s'\n",
- g_admin_commands[ i ]->command ) );
- ADMBP_end();
- return qfalse;
- }
- ADMBP( va( "^3!help: ^7help for '%s':\n",
- g_admin_commands[ i ]->command ) );
- ADMBP( va( " ^3Description: ^7%s\n", g_admin_commands[ i ]->desc ) );
- ADMBP( va( " ^3Syntax: ^7!%s\n", g_admin_commands[ i ]->command ) );
+ ADMBP( va( "^3adminhelp: ^7help for '%s':\n", admincmd->keyword ) );
+ ADMBP( va( " ^3Description: ^7%s\n", admincmd->function ) );
+ ADMBP( va( " ^3Syntax: ^7%s %s\n", admincmd->keyword,
+ admincmd->syntax ) );
+ ADMBP( va( " ^3Flag: ^7'%s'\n", admincmd->flag ) );
ADMBP_end();
return qtrue;
}
+ denied = qtrue;
}
- ADMBP( va( "^3!help: ^7no help found for '%s'\n", cmd ) );
- ADMBP_end();
+ ADMBP( va( "^3adminhelp: ^7%s '%s'\n",
+ denied ? "you do not have permission to use" : "no help found for",
+ param ) );
+ ADMBP_end( );
return qfalse;
}
}
-qboolean G_admin_admintest( gentity_t *ent, int skiparg )
+qboolean G_admin_admintest( gentity_t *ent )
{
- int i, l = 0;
- qboolean found = qfalse;
- qboolean lname = qfalse;
+ g_admin_level_t *l;
if( !ent )
{
- ADMP( "^3!admintest: ^7you are on the console.\n" );
+ ADMP( "^3admintest: ^7you are on the console.\n" );
return qtrue;
}
- for( i = 0; i < MAX_ADMIN_ADMINS && g_admin_admins[ i ]; i++ )
- {
- if( !Q_stricmp( g_admin_admins[ i ]->guid, ent->client->pers.guid ) )
- {
- found = qtrue;
- break;
- }
- }
- if( found )
- {
- l = g_admin_admins[ i ]->level;
- for( i = 0; i < MAX_ADMIN_LEVELS && g_admin_levels[ i ]; i++ )
- {
- if( g_admin_levels[ i ]->level != l )
- continue;
- if( *g_admin_levels[ i ]->name )
- {
- lname = qtrue;
- break;
- }
- }
- }
- AP( va( "print \"^3!admintest: ^7%s^7 is a level %d admin %s%s^7%s\n\"",
+ l = G_admin_level( ent->client->pers.admin ? ent->client->pers.admin->level : 0 );
+
+ AP( va( "print \"^3admintest: ^7%s^7 is a level %d admin %s%s^7%s\n\"",
ent->client->pers.netname,
- l,
- ( lname ) ? "(" : "",
- ( lname ) ? g_admin_levels[ i ]->name : "",
- ( lname ) ? ")" : "" ) );
+ l ? l->level : 0,
+ l ? "(" : "",
+ l ? l->name : "",
+ l ? ")" : "" ) );
return qtrue;
}
-qboolean G_admin_allready( gentity_t *ent, int skiparg )
+qboolean G_admin_allready( gentity_t *ent )
{
int i = 0;
gclient_t *cl;
if( !level.intermissiontime )
{
- ADMP( "^3!allready: ^7this command is only valid during intermission\n" );
+ ADMP( "^3allready: ^7this command is only valid during intermission\n" );
return qfalse;
}
@@ -5691,233 +2667,54 @@ qboolean G_admin_allready( gentity_t *ent, int skiparg )
if( cl->pers.connected != CON_CONNECTED )
continue;
- if( cl->pers.teamSelection == PTE_NONE )
+ if( cl->pers.teamSelection == TEAM_NONE )
continue;
- cl->readyToExit = 1;
- }
- AP( va( "print \"^3!allready:^7 %s^7 says everyone is READY now\n\"",
- ( ent ) ? G_admin_adminPrintName( ent ) : "console" ) );
- return qtrue;
-}
-
-qboolean G_admin_cancelvote( gentity_t *ent, int skiparg )
-{
-
- if(!level.voteTime && !level.teamVoteTime[ 0 ] && !level.teamVoteTime[ 1 ] )
- {
- ADMP( "^3!cancelvote^7: no vote in progress\n" );
- return qfalse;
- }
- level.voteNo = level.numConnectedClients;
- level.voteYes = 0;
- CheckVote( );
- level.teamVoteNo[ 0 ] = level.numConnectedClients;
- level.teamVoteYes[ 0 ] = 0;
- CheckTeamVote( PTE_HUMANS );
- level.teamVoteNo[ 1 ] = level.numConnectedClients;
- level.teamVoteYes[ 1 ] = 0;
- CheckTeamVote( PTE_ALIENS );
- AP( va( "print \"^3!cancelvote: ^7%s^7 decided that everyone voted No\n\"",
- ( ent ) ? G_admin_adminPrintName( ent ) : "console" ) );
- return qtrue;
-}
-
-qboolean G_admin_passvote( gentity_t *ent, int skiparg )
-{
- if(!level.voteTime && !level.teamVoteTime[ 0 ] && !level.teamVoteTime[ 1 ] )
- {
- ADMP( "^3!passvote^7: no vote in progress\n" );
- return qfalse;
+ cl->readyToExit = qtrue;
}
- level.voteYes = level.numConnectedClients;
- level.voteNo = 0;
- CheckVote( );
- level.teamVoteYes[ 0 ] = level.numConnectedClients;
- level.teamVoteNo[ 0 ] = 0;
- CheckTeamVote( PTE_HUMANS );
- level.teamVoteYes[ 1 ] = level.numConnectedClients;
- level.teamVoteNo[ 1 ] = 0;
- CheckTeamVote( PTE_ALIENS );
- AP( va( "print \"^3!passvote: ^7%s^7 decided that everyone voted Yes\n\"",
- ( ent ) ? G_admin_adminPrintName( ent ) : "console" ) );
+ AP( va( "print \"^3allready:^7 %s^7 says everyone is READY now\n\"",
+ ( ent ) ? ent->client->pers.netname : "console" ) );
return qtrue;
}
-static qboolean G_admin_global_pause( gentity_t *ent, int skiparg )
+qboolean G_admin_endvote( gentity_t *ent )
{
- if( level.paused )
- {
- level.pauseTime = level.time;
- ADMP( "^3!pause: ^7Game is already paused, unpause timer reset\n" );
- return qfalse;
- }
-
- level.paused = qtrue;
- level.pauseTime = level.time;
-
- level.pause_speed = g_speed.value;
- level.pause_gravity = g_gravity.value;
- level.pause_knockback = g_knockback.value;
- level.pause_ff = g_friendlyFire.integer;
- level.pause_ffb = g_friendlyBuildableFire.integer;
-
- g_speed.value = 0;
- g_gravity.value = 0;
- g_knockback.value = 0;
- g_friendlyFire.integer = 0;
- g_friendlyBuildableFire.integer = 0;
-
- CP( "cp \"^1Game is PAUSED\"" );
- AP( va( "print \"^3!pause: ^7The game has been paused by %s\n\"",
- ( ent ) ? G_admin_adminPrintName( ent ) : "console" ) );
-
- return qtrue;
-}
+ char teamName[ sizeof( "spectators" ) ] = {"s"};
+ char command[ MAX_ADMIN_CMD_LEN ];
+ team_t team;
+ qboolean cancel;
+ const char *msg;
-static qboolean G_admin_global_unpause( gentity_t *ent, int skiparg )
-{
- if( !level.paused )
+ trap_Argv( 0, command, sizeof( command ) );
+ cancel = !Q_stricmp( command, "cancelvote" );
+ if( trap_Argc() == 2 )
+ trap_Argv( 1, teamName, sizeof( teamName ) );
+ team = G_TeamFromString( teamName );
+ if( team == NUM_TEAMS )
{
- ADMP( "^3!unpause: ^7Game is not paused\n" );
+ ADMP( va( "^3%s: ^7invalid team '%s'\n", command, teamName ) );
return qfalse;
}
-
- level.paused = qfalse;
-
- g_speed.value = level.pause_speed;
- g_gravity.value = level.pause_gravity;
- g_knockback.value = level.pause_knockback;
- g_friendlyFire.integer = level.pause_ff;
- g_friendlyBuildableFire.integer = level.pause_ffb;
-
- CP( "cp \"^2Game is RESUMED\"" );
- AP( va( "print \"^3!unpause: ^7The game has been resumed by %s\n\"",
- ( ent ) ? G_admin_adminPrintName( ent ) : "console" ) );
-
- return qtrue;
-}
-
-static qboolean is_numeric(const char *str)
-{
- const char *p;
-
- if (!*str)
- return qfalse;
-
- for (p = str; *p; p++)
- if (*p < '0' || *p > '9')
- return qfalse;
-
- return qtrue;
-}
-
-qboolean G_admin_pause( gentity_t *ent, int skiparg )
-{
- int pids[ MAX_CLIENTS ];
- char name[ MAX_NAME_LENGTH ], err[ MAX_STRING_CHARS ];
- char command[ MAX_ADMIN_CMD_LEN ], *cmd;
- int i;
- int count = 0;
- gentity_t *vic;
-
- G_SayArgv( skiparg, command, sizeof( command ) );
- cmd = command;
- if( cmd && *cmd == '!' )
- cmd++;
-
- if( G_SayArgc() < 2 + skiparg )
- {
- // global pause
- if( !Q_stricmp( cmd, "pause" ) )
- return G_admin_global_pause( ent, skiparg );
- else
- return G_admin_global_unpause( ent, skiparg );
- }
- if( G_SayArgc() != 2 + skiparg )
+ msg = va( "print \"^3%s: ^7%s^7 decided that everyone voted %s\n\"",
+ command, ( ent ) ? ent->client->pers.netname : "console",
+ cancel ? "No" : "Yes" );
+ if( !level.voteTime[ team ] )
{
- ADMP( va( "^3!%s: ^7usage: !%s (^5name|slot|*^7)\n", cmd, cmd ) );
+ ADMP( va( "^3%s: ^7no vote in progress\n", command ) );
return qfalse;
}
-
- G_SayArgv( 1 + skiparg, name, sizeof( name ) );
- if( !Q_stricmp( name, "*" ) )
- {
- for( i = 0; i < MAX_CLIENTS; i++ )
- {
- vic = &g_entities[ i ];
- if( vic && vic->client &&
- vic->client->pers.connected == CON_CONNECTED )
- {
- pids[ count ] = i;
- count++;
- }
- }
- }
+ admin_log( BG_TeamName( team ) );
+ level.voteNo[ team ] = cancel ? level.numVotingClients[ team ] : 0;
+ level.voteYes[ team ] = cancel ? 0 : level.numVotingClients[ team ];
+ G_CheckVote( team );
+ if( team == TEAM_NONE )
+ AP( msg );
else
- {
- if( G_ClientNumbersFromString( name, pids ) != 1 )
- {
- G_MatchOnePlayer( pids, err, sizeof( err ) );
- ADMP( va( "^3!%s: ^7%s\n", cmd, err ) );
- return qfalse;
- }
- count = 1;
- }
-
- for( i = 0; i < count; i++ )
- {
- vic = &g_entities[ pids[ i ] ];
- if ( !vic || !vic->client ) continue;
- if( !admin_higher( ent, vic ) )
- {
- if( count == 1 )
- ADMP( va( "^3!%s: ^7sorry, but your intended victim has a higher admin"
- " level than you\n", cmd ) );
- continue;
- }
- if( vic->client->pers.paused )
- {
- if( !Q_stricmp( cmd, "pause" ) )
- {
- if( count == 1 )
- ADMP( "^3!pause: ^7player is already paused\n" );
- continue;
- }
- vic->client->pers.paused = qfalse;
- CPx( pids[ i ], "cp \"^2You've been unpaused\"" );
- if( count == 1 )
- AP( va( "print \"^3!unpause: ^7%s^7 unpaused by %s\n\"",
- vic->client->pers.netname,
- ( ent ) ? ent->client->pers.netname : "console" ) );
- }
- else
- {
- if( !Q_stricmp( cmd, "unpause" ) )
- {
- if( count == 1 )
- ADMP( "^3!unpause: ^7player is already unpaused\n" );
- continue;
- }
- if( count == 1 && ent == vic)
- {
- ADMP( "^3!pause: ^7you can not pause yourself\n" );
- continue;
- }
- vic->client->pers.paused = qtrue;
- CPx( pids[ i ], va( "cp \"^1You've been paused by ^7%s\"",
- ( ent ) ? ent->client->pers.netname : "console" ) );
- if( count == 1 )
- AP( va( "print \"^3!pause: ^7%s^7 paused by %s\n\"",
- vic->client->pers.netname,
- ( ent ) ? ent->client->pers.netname : "console" ) );
- }
- ClientUserinfoChanged( pids[ i ], qfalse );
- }
+ G_TeamCommand( team, msg );
return qtrue;
}
-qboolean G_admin_spec999( gentity_t *ent, int skiparg )
+qboolean G_admin_spec999( gentity_t *ent )
{
int i;
gentity_t *vic;
@@ -5929,146 +2726,186 @@ qboolean G_admin_spec999( gentity_t *ent, int skiparg )
continue;
if( vic->client->pers.connected != CON_CONNECTED )
continue;
- if( vic->client->pers.teamSelection == PTE_NONE )
+ if( vic->client->pers.teamSelection == TEAM_NONE )
continue;
if( vic->client->ps.ping == 999 )
{
- G_ChangeTeam( vic, PTE_NONE );
- AP( va( "print \"^3!spec999: ^7%s^7 moved ^7%s^7 to spectators\n\"",
- ( ent ) ? G_admin_adminPrintName( ent ) : "console",
+ G_ChangeTeam( vic, TEAM_NONE );
+ AP( va( "print \"^3spec999: ^7%s^7 moved %s^7 to spectators\n\"",
+ ( ent ) ? ent->client->pers.netname : "console",
vic->client->pers.netname ) );
}
}
return qtrue;
}
+
+qboolean G_admin_transform( gentity_t *ent )
+{
+ int pid;
+ char name[ MAX_NAME_LENGTH ];
+ char modelname[ MAX_NAME_LENGTH ];
+ char skin[ MAX_NAME_LENGTH ];
+ char err[ MAX_STRING_CHARS ];
+ char userinfo[ MAX_INFO_STRING ];
+ gentity_t *victim = NULL;
+ int i;
+ qboolean found = qfalse;
+
+ if (trap_Argc() < 3)
+ {
+ ADMP("^3transform: ^7usage: transform [name|slot#] [model] <skin>\n");
+ return qfalse;
+ }
-qboolean G_admin_register(gentity_t *ent, int skiparg ){
- int level = 0;
+ trap_Argv(1, name, sizeof(name));
+ trap_Argv(2, modelname, sizeof(modelname));
- if( !ent ) return qtrue;
+ strcpy(skin, "default");
+ if (trap_Argc() >= 4)
+ {
+ trap_Argv(1, skin, sizeof(skin));
+ }
- level = G_admin_level(ent);
+ pid = G_ClientNumberFromString(name, err, sizeof(err));
+ if (pid == -1)
+ {
+ ADMP(va("^3transform: ^7%s", err));
+ return qfalse;
+ }
- if( level == 0 )
- level = 1;
-
- if( !Q_stricmp( ent->client->pers.guid, "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" ) )
+ victim = &g_entities[ pid ];
+ if (victim->client->pers.connected != CON_CONNECTED)
{
- ADMP( va( "^3!register: ^7 You cannot register for name protection until you update your client. Please replace your client executable with the one at http://trem.tjw.org/backport/ and reconnect. Updating your client will also allow you to have faster map downloads.\n" ) );
+ ADMP("^3transform: ^7sorry, but your intended victim is still connecting\n");
return qfalse;
}
- if( g_newbieNumbering.integer
- && g_newbieNamePrefix.string[ 0 ]
- && !Q_stricmpn ( ent->client->pers.netname, g_newbieNamePrefix.string, strlen(g_newbieNamePrefix.string ) ) )
+ for ( i = 0; i < level.playerModelCount; i++ )
{
- ADMP( va( "^3!register: ^7 You cannot register names that begin with '%s^7'.\n",
- g_newbieNamePrefix.string ) );
+ if ( !strcmp(modelname, level.playerModel[i]) )
+ {
+ found = qtrue;
+ break;
+ }
+ }
+
+ if (!found)
+ {
+ ADMP(va("^3transform: ^7no matching model %s\n", modelname));
return qfalse;
}
- trap_SendConsoleCommand( EXEC_APPEND,va( "!setlevel %d %d;",ent - g_entities, level) );
-
- AP( va( "print \"^3!register: ^7%s^7 is now a protected nickname.\n\"", ent->client->pers.netname) );
-
+ trap_GetUserinfo(pid, userinfo, sizeof(userinfo));
+ AP( va("print \"^3transform: ^7%s^7 has been changed into %s^7 by %s\n\"",
+ victim->client->pers.netname, modelname,
+ (ent ? ent->client->pers.netname : "console")) );
+
+ Info_SetValueForKey( userinfo, "model", modelname );
+ Info_SetValueForKey( userinfo, "skin", GetSkin(modelname, skin));
+ Info_SetValueForKey( userinfo, "voice", modelname );
+ trap_SetUserinfo( pid, userinfo );
+ ClientUserinfoChanged( pid, qtrue );
+
return qtrue;
}
-qboolean G_admin_rename( gentity_t *ent, int skiparg )
+qboolean G_admin_rename( gentity_t *ent )
{
- int pids[ MAX_CLIENTS ];
+ int pid;
char name[ MAX_NAME_LENGTH ];
char newname[ MAX_NAME_LENGTH ];
- char oldname[ MAX_NAME_LENGTH ];
char err[ MAX_STRING_CHARS ];
char userinfo[ MAX_INFO_STRING ];
- char *s;
gentity_t *victim = NULL;
- if( G_SayArgc() < 3 + skiparg )
+ if( trap_Argc() < 3 )
{
- ADMP( "^3!rename: ^7usage: !rename [name] [newname]\n" );
+ ADMP( "^3rename: ^7usage: rename [name] [newname]\n" );
return qfalse;
}
- G_SayArgv( 1 + skiparg, name, sizeof( name ) );
- s = G_SayConcatArgs( 2 + skiparg );
- Q_strncpyz( newname, s, sizeof( newname ) );
- if( G_ClientNumbersFromString( name, pids ) != 1 )
+ trap_Argv( 1, name, sizeof( name ) );
+ Q_strncpyz( newname, ConcatArgs( 2 ), sizeof( newname ) );
+ if( ( pid = G_ClientNumberFromString( name, err, sizeof( err ) ) ) == -1 )
{
- G_MatchOnePlayer( pids, err, sizeof( err ) );
- ADMP( va( "^3!rename: ^7%s\n", err ) );
+ ADMP( va( "^3rename: ^7%s", err ) );
return qfalse;
}
- victim = &g_entities[ pids[ 0 ] ] ;
+ victim = &g_entities[ pid ];
if( !admin_higher( ent, victim ) )
{
- ADMP( "^3!rename: ^7sorry, but your intended victim has a higher admin"
+ ADMP( "^3rename: ^7sorry, but your intended victim has a higher admin"
" level than you\n" );
return qfalse;
}
if( !G_admin_name_check( victim, newname, err, sizeof( err ) ) )
{
- G_admin_print( ent, va( "^3!rename: Invalid name: ^7%s\n", err ) );
+ ADMP( va( "^3rename: ^7%s\n", err ) );
+ return qfalse;
+ }
+ if( victim->client->pers.connected != CON_CONNECTED )
+ {
+ ADMP( "^3rename: ^7sorry, but your intended victim is still connecting\n" );
return qfalse;
}
- level.clients[ pids[ 0 ] ].pers.nameChanges--;
- level.clients[ pids[ 0 ] ].pers.nameChangeTime = 0;
- trap_GetUserinfo( pids[ 0 ], userinfo, sizeof( userinfo ) );
- s = Info_ValueForKey( userinfo, "name" );
- Q_strncpyz( oldname, s, sizeof( oldname ) );
+ admin_log( va( "%d (%s) \"%s" S_COLOR_WHITE "\"", pid,
+ victim->client->pers.guid, victim->client->pers.netname ) );
+ admin_log( newname );
+ trap_GetUserinfo( pid, userinfo, sizeof( userinfo ) );
+ AP( va( "print \"^3rename: ^7%s^7 has been renamed to %s^7 by %s\n\"",
+ victim->client->pers.netname,
+ newname,
+ ( ent ) ? ent->client->pers.netname : "console" ) );
Info_SetValueForKey( userinfo, "name", newname );
- trap_SetUserinfo( pids[ 0 ], userinfo );
- ClientUserinfoChanged( pids[ 0 ], qtrue );
- if( strcmp( oldname, level.clients[ pids[ 0 ] ].pers.netname ) )
- AP( va( "print \"^3!rename: ^7%s^7 has been renamed to %s^7 by %s\n\"",
- oldname,
- level.clients[ pids[ 0 ] ].pers.netname,
- ( ent ) ? G_admin_adminPrintName( ent ) : "console" ) );
+ trap_SetUserinfo( pid, userinfo );
+ ClientUserinfoChanged( pid, qtrue );
return qtrue;
}
-qboolean G_admin_restart( gentity_t *ent, int skiparg )
+qboolean G_admin_restart( gentity_t *ent )
{
- char layout[ MAX_CVAR_VALUE_STRING ] = { "" };
- char teampref[ MAX_CVAR_VALUE_STRING ] = { "" };
- int i;
+ char layout[ MAX_CVAR_VALUE_STRING ] = { "" };
+ char teampref[ MAX_STRING_CHARS ] = { "" };
+ char map[ MAX_CVAR_VALUE_STRING ];
+ int i;
gclient_t *cl;
- if( G_SayArgc( ) > 1 + skiparg )
+ if( trap_Argc( ) > 1 )
{
char map[ MAX_QPATH ];
trap_Cvar_VariableStringBuffer( "mapname", map, sizeof( map ) );
- G_SayArgv( skiparg + 1, layout, sizeof( layout ) );
+ trap_Argv( 1, layout, sizeof( layout ) );
- if( Q_stricmp( layout, "keepteams" ) && Q_stricmp( layout, "keepteamslock" ) && Q_stricmp( layout, "switchteams" ) && Q_stricmp( layout, "switchteamslock" ) )
+ // Figure out which argument is which
+ if( Q_stricmp( layout, "keepteams" ) &&
+ Q_stricmp( layout, "keepteamslock" ) &&
+ Q_stricmp( layout, "switchteams" ) &&
+ Q_stricmp( layout, "switchteamslock" ) )
{
- if( !Q_stricmp( layout, "*BUILTIN*" ) ||
- trap_FS_FOpenFile( va( "layouts/%s/%s.dat", map, layout ),
- NULL, FS_READ ) > 0 )
+ if( G_LayoutExists( map, layout ) )
{
- trap_Cvar_Set( "g_layouts", layout );
+ trap_Cvar_Set( "g_nextLayout", layout );
}
else
{
- ADMP( va( "^3!restart: ^7layout '%s' does not exist\n", layout ) );
+ ADMP( va( "^3restart: ^7layout '%s' does not exist\n", layout ) );
return qfalse;
}
}
- else
+ else
{
- strcpy(layout,"");
- G_SayArgv( skiparg + 1, teampref, sizeof( teampref ) );
+ layout[ 0 ] = '\0';
+ trap_Argv( 1, teampref, sizeof( teampref ) );
}
}
-
- if( G_SayArgc( ) > 2 + skiparg )
- {
- G_SayArgv( skiparg + 2, teampref, sizeof( teampref ) );
- }
-
-
- if( !Q_stricmp( teampref, "keepteams" ) || !Q_stricmp( teampref, "keepteamslock" ) )
+
+ if( trap_Argc( ) > 2 )
+ trap_Argv( 2, teampref, sizeof( teampref ) );
+
+ admin_log( layout );
+ admin_log( teampref );
+
+ if( !Q_stricmpn( teampref, "keepteams", 9 ) )
{
for( i = 0; i < g_maxclients.integer; i++ )
{
@@ -6076,2349 +2913,716 @@ qboolean G_admin_restart( gentity_t *ent, int skiparg )
if( cl->pers.connected != CON_CONNECTED )
continue;
- if( cl->pers.teamSelection == PTE_NONE )
+ if( cl->pers.teamSelection == TEAM_NONE )
continue;
cl->sess.restartTeam = cl->pers.teamSelection;
}
- }
- else if(!Q_stricmp( teampref, "switchteams" ) || !Q_stricmp( teampref, "switchteamslock" ))
+ }
+ else if( !Q_stricmpn( teampref, "switchteams", 11 ) )
{
for( i = 0; i < g_maxclients.integer; i++ )
{
cl = level.clients + i;
- if( cl->pers.connected != CON_CONNECTED )
- continue;
- if( cl->pers.teamSelection == PTE_NONE )
+ if( cl->pers.connected != CON_CONNECTED )
continue;
- if( cl->pers.teamSelection == PTE_ALIENS )
- cl->sess.restartTeam = PTE_HUMANS;
- else if(cl->pers.teamSelection == PTE_HUMANS )
- cl->sess.restartTeam = PTE_ALIENS;
- }
+ if( cl->pers.teamSelection == TEAM_HUMANS )
+ cl->sess.restartTeam = TEAM_ALIENS;
+ else if(cl->pers.teamSelection == TEAM_ALIENS )
+ cl->sess.restartTeam = TEAM_HUMANS;
+ }
}
-
- if( !Q_stricmp( teampref, "switchteamslock" ) || !Q_stricmp( teampref, "keepteamslock" ) )
- {
+
+ if( !Q_stricmp( teampref, "switchteamslock" ) ||
+ !Q_stricmp( teampref, "keepteamslock" ) )
trap_Cvar_Set( "g_lockTeamsAtStart", "1" );
- }
- trap_SendConsoleCommand( EXEC_APPEND, "map_restart" );
-
- if(teampref[ 0 ])
- strcpy(teampref,va( "^7(with teams option: '%s^7')", teampref ));
-
- G_admin_maplog_result( "R" );
-
- AP( va( "print \"^3!restart: ^7map restarted by %s %s %s\n\"",
- ( ent ) ? G_admin_adminPrintName( ent ) : "console",
+ trap_Cvar_VariableStringBuffer( "mapname", map, sizeof( map ) );
+ G_MapConfigs( map );
+ trap_SendConsoleCommand( EXEC_APPEND, "map_restart\n" );
+
+ AP( va( "print \"^3restart: ^7map restarted by %s %s %s\n\"",
+ ( ent ) ? ent->client->pers.netname : "console",
( layout[ 0 ] ) ? va( "^7(forcing layout '%s^7')", layout ) : "",
- teampref ) );
+ ( teampref[ 0 ] ) ? va( "^7(with teams option: '%s^7')", teampref ) : "" ) );
return qtrue;
}
-qboolean G_admin_nobuild( gentity_t *ent, int skiparg )
+qboolean G_admin_nextmap( gentity_t *ent )
{
- char buffer[ MAX_STRING_CHARS ];
- int i, tmp;
-
- if( G_SayArgc() < 2 + skiparg )
- {
- ADMP( "^3!nobuild: ^7usage: !nobuild (^5enable / disable / log / remove / save^7)\n" );
+ if( level.exited )
return qfalse;
- }
-
- G_SayArgv( 1 + skiparg, buffer, sizeof( buffer ) );
-
- if( !Q_stricmp( buffer, "enable" ) || !Q_stricmp( buffer, "Enable" ) )
- {
- if( G_SayArgc() < 4 + skiparg )
- {
- ADMP( "^3!nobuild: ^7usage: !nobuild enable (^5area^7) (^5height^7)\n" );
- return qfalse;
- }
-
- if( !level.noBuilding )
- {
-
- level.noBuilding = qtrue;
-
- // Grab and set the area
- G_SayArgv( 2 + skiparg, buffer, sizeof( buffer ) );
- tmp = atoi( buffer );
- level.nbArea = tmp;
-
- // Grab and set the height
- G_SayArgv( 3 + skiparg, buffer, sizeof( buffer ) );
- tmp = atoi( buffer );
- level.nbHeight = tmp;
-
- ADMP( "^3!nobuild: ^7nobuild is now enabled, please place a buildable to spawn a marker\n" );
- return qtrue;
- }
- else
- {
- ADMP( "^3!nobuild: ^7nobuild is already enabled. type !nobuild disable to disable nobuild mode.\n" );
- return qfalse;
- }
- }
-
- if( !Q_stricmp( buffer, "disable" ) || !Q_stricmp( buffer, "Disable" ) )
- {
- if( level.noBuilding )
- {
- level.noBuilding = qfalse;
- level.nbArea = 0.0f;
- level.nbHeight = 0.0f;
- ADMP( "^3!nobuild: ^7nobuild is now disabled\n" );
- return qtrue;
- }
- else
- {
- ADMP( "^3!nobuild: ^7nobuild is disabled. type !nobuild enable (^5area^7) (^5height^7) to enable nobuild mode.\n" );
- return qfalse;
- }
- }
-
- if( !Q_stricmp( buffer, "log" ) || !Q_stricmp( buffer, "Log" ) )
- {
- ADMBP_begin();
-
- tmp = 0;
- for( i = 0; i < MAX_GENTITIES; i++ )
- {
- if( level.nbMarkers[ i ].Marker == NULL )
- continue;
-
- // This will display a start at 1, and not 0. This is to stop confusion by server ops
- ADMBP( va( "^7#%i at origin (^5%f %f %f^7)^7\n", i + 1, level.nbMarkers[ i ].Origin[0], level.nbMarkers[ i ].Origin[1], level.nbMarkers[ i ].Origin[2] ) );
- tmp++;
- }
- ADMBP( va( "^3!nobuild:^7 displaying %i marker(s)\n", tmp ) );
-
- ADMBP_end();
- return qtrue;
- }
-
- if( !Q_stricmp( buffer, "remove" ) || !Q_stricmp( buffer, "Remove" ) )
- {
- if( G_SayArgc() < 3 + skiparg )
- {
- ADMP( "^3!nobuild: ^7usage: !nobuild remove (^5marker #^7)\n" );
- return qfalse;
- }
-
- G_SayArgv( 2 + skiparg, buffer, sizeof( buffer ) );
- tmp = atoi( buffer ) - 1;
- // ^ that was to work with the display number...
-
- if( level.nbMarkers[ tmp ].Marker == NULL )
- {
- ADMP( "^3!nobuild: ^7that is not a valid marker number\n" );
- return qfalse;
- }
- // Donno why im doing this, but lets clear this...
- level.nbMarkers[ tmp ].Marker->noBuild.isNB = qfalse;
- level.nbMarkers[ tmp ].Marker->noBuild.Area = 0.0f;
- level.nbMarkers[ tmp ].Marker->noBuild.Height = 0.0f;
-
- // Free the entitiy and null it out...
- G_FreeEntity( level.nbMarkers[ tmp ].Marker );
- level.nbMarkers[ tmp ].Marker = NULL;
-
- // That is to work with the display number...
- ADMP( va( "^3!nobuild:^7 marker %i has been removed\n", tmp + 1 ) );
- return qtrue;
- }
-
- if( !Q_stricmp( buffer, "save" ) || !Q_stricmp( buffer, "Save" ) )
- {
- int i, tmp;
-
- G_NobuildSave( );
-
- tmp = 0;
- for( i = 0; i < MAX_GENTITIES; i++ )
- {
- if( level.nbMarkers[ i ].Marker == NULL )
- continue;
-
- tmp++;
- }
- ADMP( va( "^3!nobuild:^7 %i nobuild markers have been saved\n", tmp ) );
- return qtrue;
- }
- return qfalse;
-}
-
-qboolean G_admin_nextmap( gentity_t *ent, int skiparg )
-{
- AP( va( "print \"^3!nextmap: ^7%s^7 decided to load the next map\n\"",
- ( ent ) ? G_admin_adminPrintName( ent ) : "console" ) );
- level.lastWin = PTE_NONE;
+ AP( va( "print \"^3nextmap: ^7%s^7 decided to load the next map\n\"",
+ ( ent ) ? ent->client->pers.netname : "console" ) );
+ level.lastWin = TEAM_NONE;
trap_SetConfigstring( CS_WINNER, "Evacuation" );
LogExit( va( "nextmap was run by %s",
- ( ent ) ? G_admin_adminPrintName( ent ) : "console" ) );
- G_admin_maplog_result( "N" );
+ ( ent ) ? ent->client->pers.netname : "console" ) );
return qtrue;
}
-static const char *displaySchachtmeisterJudgement(const schachtmeisterJudgement_t *j,
- g_admin_namelog_t *namelog)
-{
- static char buffer[20];
-
- if (G_admin_permission_guid(namelog->guid, ADMF_INCOGNITO)) {
- Com_sprintf(buffer, sizeof(buffer), "^2 +0");
- } else if (strcmp(namelog->guid, "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX") &&
- (G_admin_permission_guid(namelog->guid, ADMF_NOAUTOBAHN) ||
- G_admin_permission_guid(namelog->guid, ADMF_IMMUNITY))) {
- Com_sprintf(buffer, sizeof(buffer), "^7 N/A ");
- } else if (!j->ratingTime) {
- Com_sprintf(buffer, sizeof(buffer), "^5 wait");
- } else {
- int color;
-
- if (j->rating >= g_schachtmeisterClearThreshold.integer)
- color = 2;
- else if (j->rating <= g_schachtmeisterAutobahnThreshold.integer)
- color = 1;
- else
- color = 3;
-
- Com_sprintf(buffer, sizeof(buffer), "^%i%+5i", color, j->rating);
- }
-
- return buffer;
-}
-
-qboolean G_admin_namelog( gentity_t *ent, int skiparg )
+qboolean G_admin_setnextmap( gentity_t *ent )
{
- int i, j;
- char search[ MAX_NAME_LENGTH ] = {""};
- char s2[ MAX_NAME_LENGTH ] = {""};
- char n2[ MAX_NAME_LENGTH ] = {""};
- char guid_stub[ 9 ];
- qboolean found = qfalse;
- int printed = 0;
+ int argc = trap_Argc();
+ char map[ MAX_QPATH ];
+ char layout[ MAX_QPATH ];
- if( G_SayArgc() > 1 + skiparg )
+ if( argc < 2 || argc > 3 )
{
- G_SayArgv( 1 + skiparg, search, sizeof( search ) );
- G_SanitiseString( search, s2, sizeof( s2 ) );
+ ADMP( "^3setnextmap: ^7usage: setnextmap [map] (layout)\n" );
+ return qfalse;
}
- ADMBP_begin();
- for( i = 0; i < MAX_ADMIN_NAMELOGS && g_admin_namelog[ i ]; i++ )
- {
- if( search[0] )
- {
- found = qfalse;
- 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 ) )
- {
- found = qtrue;
- break;
- }
- }
- if( !found )
- continue;
- }
- printed++;
- for( j = 0; j < 8; j++ )
- guid_stub[ j ] = g_admin_namelog[ i ]->guid[ j + 24 ];
- guid_stub[ j ] = '\0';
- if( g_admin_namelog[ i ]->slot > -1 )
- ADMBP( "^3" );
- ADMBP( va( "%-2s (*%s) %15s %s^7",
- (g_admin_namelog[ i ]->slot > -1 ) ?
- va( "%d", g_admin_namelog[ i ]->slot ) : "-",
- guid_stub, g_admin_namelog[ i ]->ip,
- displaySchachtmeisterJudgement( &g_admin_namelog[ i ]->smj, g_admin_namelog[ i ] ) ) );
- for( j = 0; j < MAX_ADMIN_NAMELOG_NAMES &&
- g_admin_namelog[ i ]->name[ j ][ 0 ]; j++ )
- {
- ADMBP( va( " '%s^7'", g_admin_namelog[ i ]->name[ j ] ) );
- }
- ADMBP( "\n" );
- }
- ADMBP( va( "^3!namelog:^7 %d recent clients found\n", printed ) );
- ADMBP_end();
- return qtrue;
-}
-qboolean G_admin_lock( gentity_t *ent, int skiparg )
-{
- char teamName[2] = {""};
- pTeam_t team;
+ trap_Argv( 1, map, sizeof( map ) );
- if( G_SayArgc() < 2 + skiparg )
+ if( !G_MapExists( map ) )
{
- ADMP( "^3!lock: ^7usage: !lock [a|h]\n" );
- return qfalse;
- }
- G_SayArgv( 1 + skiparg, teamName, sizeof( teamName ) );
- if( teamName[ 0 ] == 'a' || teamName[ 0 ] == 'A' )
- team = PTE_ALIENS;
- else if( teamName[ 0 ] == 'h' || teamName[ 0 ] == 'H' )
- team = PTE_HUMANS;
- else
- {
- ADMP( va( "^3!lock: ^7invalid team\"%c\"\n", teamName[0] ) );
+ ADMP( va( "^3setnextmap: ^7map '%s' does not exist\n", map ) );
return qfalse;
}
- if( team == PTE_ALIENS )
+ if( argc > 2 )
{
- if( level.alienTeamLocked )
- {
- ADMP( "^3!lock: ^7Alien team is already locked\n" );
- return qfalse;
- }
- else
- level.alienTeamLocked = qtrue;
- }
- else if( team == PTE_HUMANS ) {
- if( level.humanTeamLocked )
+ trap_Argv( 2, layout, sizeof( layout ) );
+
+ if( !G_LayoutExists( map, layout ) )
{
- ADMP( "^3!lock: ^7Human team is already locked\n" );
+ ADMP( va( "^3setnextmap: ^7layout '%s' does not exist for map '%s'\n", layout, map ) );
return qfalse;
}
- else
- level.humanTeamLocked = qtrue;
- }
- AP( va( "print \"^3!lock: ^7%s team has been locked by %s\n\"",
- ( team == PTE_ALIENS ) ? "Alien" : "Human",
- ( ent ) ? G_admin_adminPrintName( ent ) : "console" ) );
- return qtrue;
-}
-
-qboolean G_admin_unlock( gentity_t *ent, int skiparg )
-{
- char teamName[2] = {""};
- pTeam_t team;
-
- if( G_SayArgc() < 2 + skiparg )
- {
- ADMP( "^3!unlock: ^7usage: !unlock [a|h]\n" );
- return qfalse;
+ trap_Cvar_Set( "g_nextLayout", layout );
}
- G_SayArgv( 1 + skiparg, teamName, sizeof( teamName ) );
- if( teamName[ 0 ] == 'a' || teamName[ 0 ] == 'A' )
- team = PTE_ALIENS;
- else if( teamName[ 0 ] == 'h' || teamName[ 0 ] == 'H' )
- team = PTE_HUMANS;
else
- {
- ADMP( va( "^3!unlock: ^7invalid team\"%c\"\n", teamName[0] ) );
- return qfalse;
- }
-
- if( team == PTE_ALIENS )
- {
- if( !level.alienTeamLocked )
- {
- ADMP( "^3!unlock: ^7Alien team is not currently locked\n" );
- return qfalse;
- }
- else
- level.alienTeamLocked = qfalse;
- }
- else if( team == PTE_HUMANS ) {
- if( !level.humanTeamLocked )
- {
- ADMP( "^3!unlock: ^7Human team is not currently locked\n" );
- return qfalse;
- }
- else
- level.humanTeamLocked = qfalse;
- }
+ trap_Cvar_Set( "g_nextLayout", "" );
+
+ trap_Cvar_Set( "g_nextMap", map );
- AP( va( "print \"^3!unlock: ^7%s team has been unlocked by %s\n\"",
- ( team == PTE_ALIENS ) ? "Alien" : "Human",
- ( ent ) ? G_admin_adminPrintName( ent ) : "console" ) );
+ AP( va( "print \"^3setnextmap: ^7%s^7 has set the next map to '%s'%s\n\"",
+ ( ent ) ? ent->client->pers.netname : "console", map,
+ argc > 2 ? va( " with layout '%s'", layout ) : "" ) );
return qtrue;
-}
+}
-qboolean G_admin_designate( gentity_t *ent, int skiparg )
+static qboolean namelog_matchip( void *namelog, const void *ip )
{
- int pids[ MAX_CLIENTS ];
- char name[ MAX_NAME_LENGTH ], err[ MAX_STRING_CHARS ];
- char command[ MAX_ADMIN_CMD_LEN ], *cmd;
- gentity_t *vic;
-
- if( G_SayArgc() < 2 + skiparg )
- {
- ADMP( "^3!designate: ^7usage: designate [name|slot#]\n" );
- return qfalse;
- }
- G_SayArgv( skiparg, command, sizeof( command ) );
- cmd = command;
- if( cmd && *cmd == '!' )
- cmd++;
- G_SayArgv( 1 + skiparg, name, sizeof( name ) );
- if( G_ClientNumbersFromString( name, pids ) != 1 )
- {
- G_MatchOnePlayer( pids, err, sizeof( err ) );
- ADMP( va( "^3!designate: ^7%s\n", err ) );
- return qfalse;
- }
- if( !admin_higher( ent, &g_entities[ pids[ 0 ] ] ) &&
- !Q_stricmp( cmd, "undesignate" ) )
- {
- ADMP( "^3!designate: ^7sorry, but your intended victim has a higher admin"
- " level than you\n" );
- return qfalse;
- }
- vic = &g_entities[ pids[ 0 ] ];
- if( vic->client->pers.designatedBuilder == qtrue )
+ int i;
+ namelog_t *n = (namelog_t *)namelog;
+ for( i = 0; i < MAX_NAMELOG_ADDRS && n->ip[ i ].str[ 0 ]; i++ )
{
- if( !Q_stricmp( cmd, "designate" ) )
- {
- ADMP( "^3!designate: ^7player is already designated builder\n" );
+ if( G_AddressCompare( &n->ip[ i ], (addr_t *)ip ) ||
+ G_AddressCompare( (addr_t *)ip, &n->ip[ i ] ) )
return qtrue;
- }
- vic->client->pers.designatedBuilder = qfalse;
- CPx( pids[ 0 ], "cp \"^1Your designation has been revoked\"" );
- AP( va(
- "print \"^3!designate: ^7%s^7's designation has been revoked by %s\n\"",
- vic->client->pers.netname,
- ( ent ) ? G_admin_adminPrintName( ent ) : "console" ) );
- G_CheckDBProtection( );
}
- else
+ return qfalse;
+}
+static qboolean namelog_matchname( void *namelog, const void *name )
+{
+ char match[ MAX_NAME_LENGTH ];
+ int i;
+ namelog_t *n = (namelog_t *)namelog;
+ for( i = 0; i < MAX_NAMELOG_NAMES && n->name[ i ][ 0 ]; i++ )
{
- if( !Q_stricmp( cmd, "undesignate" ) )
- {
- ADMP( "^3!undesignate: ^7player is not currently designated builder\n" );
+ G_SanitiseString( n->name[ i ], match, sizeof( match ) );
+ if( strstr( match, (const char *)name ) )
return qtrue;
- }
- vic->client->pers.designatedBuilder = qtrue;
- CPx( pids[ 0 ], "cp \"^1You've been designated\"" );
- AP( va( "print \"^3!designate: ^7%s^7 has been designated by ^7%s\n\"",
- vic->client->pers.netname,
- ( ent ) ? G_admin_adminPrintName( ent ) : "console" ) );
}
- return qtrue;
+ return qfalse;
}
+static void namelog_out( void *namelog, char *str )
+{
+ namelog_t *n = (namelog_t *)namelog;
+ char *p = str;
+ int l, l2 = MAX_STRING_CHARS, i;
+ const char *scolor;
- //!Warn by Gate (Daniel Evans)
-qboolean G_admin_warn( gentity_t *ent, int skiparg )
-{//mostly copy and paste with the proper lines altered from !mute and !kick
- int pids[ MAX_CLIENTS ];
- char name[ MAX_NAME_LENGTH ], *reason, err[ MAX_STRING_CHARS ];
- int minargc;
- gentity_t *vic;
-
- minargc = 3 + skiparg;
- if( G_admin_permission( ent, ADMF_UNACCOUNTABLE ) )
- minargc = 2 + skiparg;
-
- if( G_SayArgc() < minargc )
+ if( n->slot > -1 )
{
- ADMP( "^3!warn: ^7usage: warn [name] [reason]\n" );
- return qfalse;
+ scolor = S_COLOR_YELLOW;
+ l = Q_snprintf( p, l2, "%s%-2d", scolor, n->slot );
+ p += l;
+ l2 -= l;
}
- G_SayArgv( 1 + skiparg, name, sizeof( name ) );
- reason = G_SayConcatArgs( 2 + skiparg );
- if( G_ClientNumbersFromString( name, pids ) != 1 )
- {
- G_MatchOnePlayer( pids, err, sizeof( err ) );
- ADMP( va( "^3!warn: ^7%s\n", err ) );
- return qfalse;
- }
- if( !admin_higher( ent, &g_entities[ pids[ 0 ] ] ) )
+ else
{
- ADMP( "^3!warn: ^7sorry, but your intended victim has a higher admin"
- " level than you.\n" );
- return qfalse;
+ *p++ = '-';
+ *p++ = ' ';
+ *p = '\0';
+ l2 -= 2;
+ scolor = S_COLOR_WHITE;
}
-
- vic = &g_entities[ pids[ 0 ] ];
- //next line is the onscreen warning
- CPx( pids[ 0 ],va("cp \"^1You have been warned by an administrator.\n ^3Cease immediately or face admin action!\n^1 %s%s\"",(*reason)? "REASON: " : "" ,(*reason)? reason : "") );
- AP( va( "print \"^3!warn: ^7%s^7 has been warned to cease and desist: %s by %s \n\"",
- vic->client->pers.netname, (*reason) ? reason : "his current activity",
- ( ent ) ? G_admin_adminPrintName( ent ) : "console" ) );//console announcement
- return qtrue;
-}
-
-qboolean G_admin_putmespec( gentity_t *ent, int skiparg )
-{
- if( !ent )
+
+ for( i = 0; i < MAX_NAMELOG_ADDRS && n->ip[ i ].str[ 0 ]; i++ )
{
- ADMP( "!specme: sorry, but console isn't allowed on the spectators team\n");
- return qfalse;
+ l = Q_snprintf( p, l2, " %s", n->ip[ i ].str );
+ p += l;
+ l2 -= l;
}
- if( level.paused )
+ for( i = 0; i < MAX_NAMELOG_NAMES && n->name[ i ][ 0 ]; i++ )
{
- ADMP("!specme: disabled when game is paused\n");
- return qfalse;
- }
-
- if(ent->client->pers.teamSelection == PTE_NONE)
- return qfalse;
-
- //guard against build timer exploit
- if( ent->client->pers.teamSelection != PTE_NONE && ent->client->sess.sessionTeam != TEAM_SPECTATOR &&
- ( ent->client->ps.stats[ STAT_PCLASS ] == PCL_ALIEN_BUILDER0 ||
- ent->client->ps.stats[ STAT_PCLASS ] == PCL_ALIEN_BUILDER0_UPG ||
- BG_InventoryContainsWeapon( WP_HBUILD, ent->client->ps.stats ) ||
- BG_InventoryContainsWeapon( WP_HBUILD2, ent->client->ps.stats ) ) &&
- ent->client->ps.stats[ STAT_MISC ] > 0 )
- {
- ADMP("!specme: You cannot leave your team until the build timer expires");
- return qfalse;
+ l = Q_snprintf( p, l2, " '" S_COLOR_WHITE "%s%s'%s", n->name[ i ], scolor,
+ i == n->nameOffset ? "*" : "" );
+ p += l;
+ l2 -= l;
}
-
- G_ChangeTeam( ent, PTE_NONE );
- AP( va("print \"^3!specme: ^7%s^7 decided to join the spectators\n\"", ent->client->pers.netname ) );
- return qtrue;
}
-
-qboolean G_admin_slap( gentity_t *ent, int skiparg )
+qboolean G_admin_namelog( gentity_t *ent )
{
- int pids[ MAX_CLIENTS ];
- char name[ MAX_NAME_LENGTH ], err[ MAX_STRING_CHARS ];
- gentity_t *vic;
- vec3_t dir;
-
- if( level.intermissiontime ) return qfalse;
+ char search[ MAX_NAME_LENGTH ] = {""};
+ char s2[ MAX_NAME_LENGTH ] = {""};
+ addr_t ip;
+ qboolean ipmatch = qfalse;
+ int start = MAX_CLIENTS, i;
- if( G_SayArgc() < 2 + skiparg )
+ if( trap_Argc() == 3 )
{
- ADMP( "^3!slap: ^7usage: !slap [name|slot#]\n" );
- return qfalse;
+ trap_Argv( 2, search, sizeof( search ) );
+ start = atoi( search );
}
-
- G_SayArgv( 1 + skiparg, name, sizeof( name ) );
- if( G_ClientNumbersFromString( name, pids ) != 1 )
+ if( trap_Argc() > 1 )
{
- G_MatchOnePlayer( pids, err, sizeof( err ) );
- ADMP( va( "^3!slap: ^7%s\n", err ) );
- return qfalse;
+ trap_Argv( 1, search, sizeof( search ) );
+ i = 0;
+ if( trap_Argc() == 2 )
+ for( i = search[ 0 ] == '-'; isdigit( search[ i ] ); i++ );
+ if( !search[ i ] )
+ start = atoi( search );
+ else if( !( ipmatch = G_AddressParse( search, &ip ) ) )
+ G_SanitiseString( search, s2, sizeof( s2 ) );
}
- vic = &g_entities[ pids[ 0 ] ];
- if( !vic )
- {
- ADMP( "^3!slap: ^7bad target\n" );
- return qfalse;
- }
- if( vic == ent )
- {
- ADMP( "^3!slap: ^7sorry, you cannot slap yourself\n" );
- return qfalse;
- }
- if( !admin_higher( ent, vic ) )
- {
- ADMP( "^3!slap: ^7sorry, but your intended victim has a higher admin"
- " level than you\n" );
- return qfalse;
- }
- if( vic->client->pers.teamSelection == PTE_NONE ||
- vic->client->pers.classSelection == PCL_NONE )
- {
- ADMP( "^3!slap: ^7can't slap spectators\n" );
- return qfalse;
- }
+ admin_search( ent, "namelog", "recent players",
+ ipmatch ? namelog_matchip : namelog_matchname, namelog_out, level.namelogs,
+ ipmatch ? (void *)&ip : s2, start, MAX_CLIENTS, MAX_ADMIN_LISTITEMS );
+ return qtrue;
+}
- // knockback in a random direction
- dir[0] = crandom();
- dir[1] = crandom();
- dir[2] = random();
- G_Knockback( vic, dir, g_slapKnockback.integer );
+/*
+==================
+G_NamelogFromString
- trap_SendServerCommand( vic-g_entities,
- va( "cp \"%s^7 is not amused\n\"",
- ( ent ) ? G_admin_adminPrintName( ent ) : "console" ) );
+This is similar to G_ClientNumberFromString but for namelog instead
+Returns NULL if not exactly 1 match
+==================
+*/
+namelog_t *G_NamelogFromString( gentity_t *ent, char *s )
+{
+ namelog_t *p, *m = NULL;
+ int i, found = 0;
+ char n2[ MAX_NAME_LENGTH ] = {""};
+ char s2[ MAX_NAME_LENGTH ] = {""};
- if( g_slapDamage.integer > 0 )
+ if( !s[ 0 ] )
+ return NULL;
+
+ // if a number is provided, it is a clientnum or namelog id
+ for( i = 0; s[ i ] && isdigit( s[ i ] ); i++ );
+ if( !s[ i ] )
{
- int damage;
+ i = atoi( s );
- if( G_SayArgc() > 2 + skiparg )
+ if( i >= 0 && i < level.maxclients )
{
- char dmg_str[ MAX_STRING_CHARS ];
- G_SayArgv( 2 + skiparg, dmg_str, sizeof( dmg_str ) );
- damage = atoi(dmg_str);
- if( damage < 0 ) damage = 0;
+ if( level.clients[ i ].pers.connected != CON_DISCONNECTED )
+ return level.clients[ i ].pers.namelog;
}
- else
+ else if( i >= MAX_CLIENTS )
{
- if( g_slapDamage.integer > 100 ) g_slapDamage.integer = 100;
- damage = BG_FindHealthForClass( vic->client->ps.stats[ STAT_PCLASS ] ) *
- g_slapDamage.integer / 100;
- if( damage < 1 ) damage = 1;
+ for( p = level.namelogs; p; p = p->next )
+ {
+ if( p->id == i )
+ break;
+ }
+ if( p )
+ return p;
}
- vic->health -= damage;
- vic->client->ps.stats[ STAT_HEALTH ] = vic->health;
- vic->lastDamageTime = level.time;
- if( vic->health <= 0 )
- {
- vic->flags |= FL_NO_KNOCKBACK;
- vic->enemy = &g_entities[ pids[ 0 ] ];
- vic->die( vic, ent, ent, damage, MOD_SLAP );
- }
- else if( vic->pain )
- {
- vic->pain( vic, &g_entities[ pids[ 0 ] ], damage );
- }
+ return NULL;
}
- return qtrue;
-}
-qboolean G_admin_drop( gentity_t *ent, int skiparg )
-{
- int pids[ MAX_CLIENTS ];
- char name[ MAX_NAME_LENGTH ], err[ MAX_STRING_CHARS ];
+ // check for a name match
+ G_SanitiseString( s, s2, sizeof( s2 ) );
- if( G_SayArgc() < 2 + skiparg )
+ for( p = level.namelogs; p; p = p->next )
{
- ADMP( "^3!drop: ^7usage: !drop [name|slot#] [message]\n" );
- return qfalse;
- }
+ for( i = 0; i < MAX_NAMELOG_NAMES && p->name[ i ][ 0 ]; i++ )
+ {
+ G_SanitiseString( p->name[ i ], n2, sizeof( n2 ) );
- G_SayArgv( 1 + skiparg, name, sizeof( name ) );
- if( G_ClientNumbersFromString( name, pids ) != 1 )
- {
- G_MatchOnePlayer( pids, err, sizeof( err ) );
- ADMP( va( "^3!drop: ^7%s\n", err ) );
- return qfalse;
- }
+ // if this is an exact match to a current player
+ if( i == p->nameOffset && p->slot > -1 && !strcmp( s2, n2 ) )
+ return p;
- if( !admin_higher( ent, &g_entities[ pids[ 0 ] ] ) )
- {
- ADMP( "^3!drop: ^7sorry, but your intended victim has a higher admin"
- " level than you\n" );
- return qfalse;
+ if( strstr( n2, s2 ) )
+ m = p;
+ }
+
+ if( m == p )
+ found++;
}
- // victim's message
- if( G_SayArgc() > 2 + skiparg )
- trap_SendServerCommand( pids[ 0 ],
- va( "disconnect \"You have been dropped.\n%s^7\n\"",
- G_SayConcatArgs( 2 + skiparg ) ) );
- else
- trap_SendServerCommand( pids[ 0 ], va( "disconnect" ) );
+ if( found == 1 )
+ return m;
- // server message
- trap_DropClient( pids[ 0 ], va( "disconnected" ) );
+ if( found > 1 )
+ admin_search( ent, "namelog", "recent players", namelog_matchname,
+ namelog_out, level.namelogs, s2, 0, MAX_CLIENTS, -1 );
- return qtrue;
+ return NULL;
}
-qboolean G_admin_buildlog( gentity_t *ent, int skiparg )
+qboolean G_admin_lock( gentity_t *ent )
{
-#define LOG_DISPLAY_LENGTH 10
- buildHistory_t *ptr;
- gentity_t *builder = NULL;
- int skip = 0, start = 0, lastID = -1, firstID = -1, i, len, matchlen = 0;
- pTeam_t team = PTE_NONE;
- char message[ MAX_STRING_CHARS ], *teamchar;
- char *name, *action, *buildablename, markstring[ MAX_STRING_CHARS ];
- if( !g_buildLogMaxLength.integer )
- {
- ADMP( "^3!buildlog: ^7build logging is disabled" );
- return qfalse;
- }
- if( G_SayArgc( ) >= 2 + skiparg )
- {
- for( i = 1; i + skiparg < G_SayArgc( ); i++ )
- {
- char argbuf[ 64 ], err[ MAX_STRING_CHARS ];
- int x = 0, pids[ MAX_CLIENTS ];
- G_SayArgv( i + skiparg, argbuf, sizeof argbuf );
- switch( argbuf[ 0 ])
- {
- case 'x':
- x = 1;
- default:
- skip = atoi( argbuf + x );
- start = 0;
- break;
- case '#':
- start = atoi( argbuf + 1 );
- skip = 0;
- break;
- case '-':
- if(G_ClientNumbersFromString(argbuf + 1, pids) != 1)
- {
- G_MatchOnePlayer(pids, err, sizeof(err));
- ADMP(va("^3!revert: ^7%s\n", err));
- return qfalse;
- }
- builder = g_entities + *pids;
- break;
- case 'A':
- case 'a':
- team = PTE_ALIENS;
- break;
- case 'H':
- case 'h':
- team = PTE_HUMANS;
- break;
- }
- }
- }
- // !buildlog can be abused, so let everyone know when it is used
- AP( va( "print \"^3!buildlog: ^7%s^7 requested a log of recent building"
- " activity\n\"", ( ent ) ? G_admin_adminPrintName( ent ) : "console" ) );
- len = G_CountBuildLog( ); // also clips the log if too long
- if( !len )
- {
- ADMP( "^3!buildlog: ^7no build log found\n" );
- return qfalse;
- }
- if( start )
- {
- // set skip based on start
- for( ptr = level.buildHistory; ptr && ptr->ID != start;
- ptr = ptr->next, skip++ );
- if( !ptr )
- {
- ADMP( "^3!buildlog: ^7log ID not found\n" );
- skip = 0;
- }
- }
- // ensure skip is a useful value
- if( skip > len - LOG_DISPLAY_LENGTH )
- skip = len - LOG_DISPLAY_LENGTH;
- *message = '\0';
- // skip to start entry
- for( ptr = level.buildHistory, i = len; ptr && i > len - skip;
- ptr = ptr->next )
- {
- // these checks could perhaps be done more efficiently but they are cheap
- // in processor time so I'm not worrying
- if( team != PTE_NONE && team != BG_FindTeamForBuildable( ptr->buildable ) )
- continue;
- if( builder && builder != ptr->ent )
- continue;
- matchlen++;
- i--;
- }
- for( ; i + LOG_DISPLAY_LENGTH > len - skip && i > 0; i--, ptr = ptr->next )
- {
- if( !ptr )
- break; // run out of log
- *markstring = '\0'; // reinit markstring
- // check team
- if( ( team != PTE_NONE && team != BG_FindTeamForBuildable( ptr->buildable ) )
- || ( builder && builder != ptr->ent ) )
- {
- skip++; // loop an extra time because we skipped one
- continue;
- }
- if( lastID < 0 )
- lastID = ptr->ID;
- firstID = ptr->ID;
- matchlen++;
- // set name to the ent's current name or last recorded name
- if( ptr->ent )
- {
- if( ptr->ent->client )
- name = ptr->ent->client->pers.netname;
- else
- name = "<world>"; // any non-client action
- }
- else
- name = ptr->name;
- switch( ptr->fate )
- {
- case BF_BUILT:
- action = "^2built^7 a";
- break;
- case BF_DECONNED:
- action = "^3DECONSTRUCTED^7 a";
- break;
- case BF_DESTROYED:
- action = "destroyed a";
- break;
- case BF_TEAMKILLED:
- action = "^1TEAMKILLED^7 a";
- break;
- default:
- action = "\0"; // erm
- break;
- }
- // handle buildables removed by markdecon
- if( ptr->marked )
- {
- buildHistory_t *mark;
- int j, markdecon[ BA_NUM_BUILDABLES ], and = 2;
- char bnames[ 32 ], *article;
- mark = ptr;
- // count the number of buildables
- memset( markdecon, 0, sizeof( markdecon ) );
- while( ( mark = mark->marked ) )
- markdecon[ mark->buildable ]++;
- // reverse order makes grammar easier
- for( j = BA_NUM_BUILDABLES; j >= 0; j-- )
- {
- buildablename = BG_FindHumanNameForBuildable( j );
- // plural is easy
- if( markdecon[ j ] > 1 )
- Com_sprintf( bnames, 32, "%d %ss", markdecon[ j ], buildablename );
- // use an appropriate article
- else if( markdecon[ j ] == 1 )
- {
- if( BG_FindUniqueTestForBuildable( j ) )
- article = "the"; // if only one
- else if( strchr( "aeiouAEIOU", *buildablename ) )
- article = "an"; // if first char is vowel
- else
- article = "a";
- Com_sprintf( bnames, 32, "%s %s", article, buildablename );
- }
- else
- continue; // none of this buildable
- // C grammar: x, y, and z
- // the integer and is 2 initially, the test means it is used on the
- // second sprintf only, the reverse order makes this second to last
- // the comma is only printed if there is already some markstring i.e.
- // not the first time ( which would put it on the end of the string )
- Com_sprintf( markstring, sizeof( markstring ), "%s%s %s%s", bnames,
- ( *markstring ) ? "," : "", ( and-- == 1 ) ? "and " : "", markstring );
- }
- }
- buildablename = BG_FindHumanNameForBuildable( ptr->buildable );
- switch( BG_FindTeamForBuildable( ptr->buildable ) )
- {
- case PTE_ALIENS:
- teamchar = "^1A";
- break;
- case PTE_HUMANS:
- teamchar = "^4H";
- break;
- default:
- teamchar = " "; // space so it lines up neatly
- break;
- }
- // prepend the information to the string as we go back in buildhistory
- // so the earliest events are at the top
- Com_sprintf( message, MAX_STRING_CHARS, "%3d %s^7 %s^7 %s%s %s%s%s\n%s",
- ptr->ID, teamchar, name, action,
- ( strchr( "aeiouAEIOU", buildablename[ 0 ] ) ) ? "n" : "",
- buildablename, ( markstring[ 0 ] ) ? ", removing " : "",
- markstring, message );
- }
- for( ; ptr; ptr = ptr->next )
- {
- if( builder && builder != ptr->ent )
- continue;
- if( team != PTE_NONE && team != BG_FindTeamForBuildable( ptr->buildable ) )
- continue;
- matchlen++;
- }
- if( matchlen )
- ADMP( va( "%s^3!buildlog: showing log entries %d - %d of %d\n", message,
- firstID, lastID, matchlen ) );
- else
- ADMP( "^3!buildlog: ^7no log entries match those criteria\n" );
- return qtrue;
-}
+ char command[ MAX_ADMIN_CMD_LEN ];
+ char teamName[ sizeof( "aliens" ) ];
+ team_t team;
+ qboolean lock, fail = qfalse;
-qboolean G_admin_revert( gentity_t *ent, int skiparg )
-{
- int i = 0, j = 0, repeat = 1, ID = 0, len, matchlen=0;
- pTeam_t team = PTE_NONE;
- qboolean force = qfalse, reached = qfalse;
- gentity_t *builder = NULL, *targ;
- buildHistory_t *ptr, *tmp, *mark, *prev;
- vec3_t dist;
- char argbuf[ 64 ], *name, *bname, *action, *article;
- len = G_CountBuildLog( );
- if( !len )
- {
- ADMP( "^3!revert: ^7no build log found\n" );
- return qfalse;
- }
- if( G_SayArgc( ) < 2 + skiparg )
+ trap_Argv( 0, command, sizeof( command ) );
+ if( trap_Argc() < 2 )
{
- ADMP( "^3!revert: ^7usage: !revert (^5xnum^7) (^5#ID^7) (^5-name|num^7) (^5a|h^7)\n" );
+ ADMP( va( "^3%s: ^7usage: %s [a|h]\n", command, command ) );
return qfalse;
}
- for( i = 1; i + skiparg < G_SayArgc( ); i++ )
- {
- char arg[ 64 ], err[ MAX_STRING_CHARS ];
- int pids[ MAX_CLIENTS ];
- G_SayArgv( i + skiparg, arg, sizeof arg );
- switch( arg[ 0 ])
- {
- case 'x':
- repeat = atoi( arg + 1 );
- break;
- case '#':
- ID = atoi( arg + 1 );
- break;
- case '-':
- if(G_ClientNumbersFromString(arg + 1, pids) != 1)
- {
- G_MatchOnePlayer(pids, err, sizeof err);
- ADMP(va("^3!revert: ^7%s\n", err));
- return qfalse;
- }
- builder = g_entities + *pids;
- break;
- case 'A':
- case 'a':
- team = PTE_ALIENS;
- break;
- case 'H':
- case 'h':
- team = PTE_HUMANS;
- break;
- case '!':
- force = qtrue;
- break;
- default:
- ADMP( "^3!revert: ^7usage: !revert (^5xnum^7) (^5#ID^7) (^5-name|num^7) (^5a|h^7)\n" );
- return qfalse;
- }
- }
- if( repeat > 25 )
- {
- ADMP( "^3!revert: ^7to avoid flooding, can only revert 25 builds at a time\n" );
- repeat = 25;
- }
- for( i = 0, ptr = prev = level.buildHistory; repeat > 0; repeat--, j = 0 )
+ lock = !Q_stricmp( command, "lock" );
+ trap_Argv( 1, teamName, sizeof( teamName ) );
+ team = G_TeamFromString( teamName );
+
+ if( team == TEAM_ALIENS )
{
- if( !ptr )
- break; // run out of bhist
- if( !reached && ID )
- {
- if( ptr->ID == ID )
- reached = qtrue;
- else
- {
- prev = ptr;
- ptr = ptr->next;
- repeat++;
- continue;
- }
- }
- if( ( team != PTE_NONE &&
- team != BG_FindTeamForBuildable( ptr->buildable ) ) ||
- ( builder && builder != ptr->ent ))
- {
- // team doesn't match, so skip this ptr and reset prev
- prev = ptr;
- ptr = ptr->next;
- // we don't want to count this one so counteract the decrement by the for
- repeat++;
- continue;
- }
- // get the ent's current or last recorded name
- if( ptr->ent )
- {
- if( ptr->ent->client )
- name = ptr->ent->client->pers.netname;
- else
- name = "<world>"; // non-client actions
- }
+ if( level.alienTeamLocked == lock )
+ fail = qtrue;
else
- name = ptr->name;
- bname = BG_FindHumanNameForBuildable( ptr->buildable );
- action = "";
- switch( ptr->fate )
- {
- case BF_BUILT:
- action = "^2build^7";
- for( j = MAX_CLIENTS, targ = g_entities + j;
- j < level.num_entities; j++, targ++ )
- {
- // easy checks first to save time
- if( targ->s.eType != ET_BUILDABLE )
- continue;
- if( targ->s.modelindex != ptr->buildable )
- continue;
- VectorSubtract( targ->s.pos.trBase, ptr->origin, dist );
-#define FIND_BUILDABLE_TOLERANCE 5
- if( VectorLength( dist ) > FIND_BUILDABLE_TOLERANCE )
- continue; // number is somewhat arbitrary, watch for false pos/neg
- // if we didn't continue then it's this one, unlink it but we can't
- // free it yet, because the markdecon buildables might not place
- trap_UnlinkEntity( targ );
- break;
- }
- // if there are marked buildables to replace, and we aren't overriding
- // space check, check they can fit before acting
- if( ptr->marked && !force )
- {
- for( mark = ptr->marked; mark; mark = mark->marked )
- if( !G_RevertCanFit( mark ) )
- {
- trap_LinkEntity( targ ); // put it back, we failed
- // scariest sprintf ever:
- Com_sprintf( argbuf, sizeof argbuf, "%s%s%s%s%s%s%s!",
- ( repeat > 1 ) ? "x" : "", ( repeat > 1 ) ? va( "%d ", repeat ) : "",
- ( ID ) ? "#" : "", ( ID ) ? va( "%d ", ptr->ID ) : "",
- ( builder ) ? "-" : "", ( builder ) ? va( "%d ", builder - g_entities ) : "",
- ( team == PTE_ALIENS ) ? "a " : ( team == PTE_HUMANS ) ? "h " : "" );
- ADMP( va( "^3!revert: ^7revert aborted: reverting this %s would conflict with "
- "another buildable, use ^3!revert %s ^7to override\n", action, argbuf ) );
- return qfalse;
- }
- }
- // Prevent teleport glitch when reverting an occupied hovel
- if( targ->s.modelindex == BA_A_HOVEL &&
- targ->active )
- {
- gentity_t *builder = targ->builder;
- vec3_t newOrigin;
- vec3_t newAngles;
-
- VectorCopy( targ->s.angles, newAngles );
- newAngles[ ROLL ] = 0;
-
- VectorCopy( targ->s.origin, newOrigin );
- VectorMA( newOrigin, 1.0f, targ->s.origin2, newOrigin );
-
- //prevent lerping
- builder->client->ps.eFlags ^= EF_TELEPORT_BIT;
- builder->client->ps.eFlags &= ~EF_NODRAW;
- G_UnlaggedClear( builder );
-
- G_SetOrigin( builder, newOrigin );
- VectorCopy( newOrigin, builder->client->ps.origin );
- G_SetClientViewAngle( builder, newAngles );
-
- //client leaves hovel
- builder->client->ps.stats[ STAT_STATE ] &= ~SS_HOVELING;
- }
-
- // if we haven't returned yet then we're good to go, free it
- G_FreeEntity( targ );
- // put the marked buildables back and mark them again
- if( ptr->marked ) // there may be a more efficient way of doing this
- {
- for( mark = ptr->marked; mark; mark = mark->marked )
- G_SpawnRevertedBuildable( mark, qtrue );
- }
- break;
- case BF_DECONNED:
- if( !action[ 0 ] ) action = "^3deconstruction^7";
- case BF_TEAMKILLED:
- if( !action[ 0 ] ) action ="^1TEAMKILL^7";
- case BF_DESTROYED:
- if( !action[ 0 ] ) action = "destruction";
- // if we're not overriding and the replacement can't fit, as before
- if( !force && !G_RevertCanFit( ptr ) )
- {
- Com_sprintf( argbuf, sizeof argbuf, "%s%s%s%s%s%s%s!",
- ( repeat > 1 ) ? "x" : "", ( repeat > 1 ) ? va( "%d ", repeat ) : "",
- ( ID ) ? "#" : "", ( ID ) ? va( "%d ", ptr->ID ) : "",
- ( builder ) ? "-" : "", ( builder ) ? va( "%d ", builder - g_entities ) : "",
- ( team == PTE_ALIENS ) ? "a " : ( team == PTE_HUMANS ) ? "h " : "" );
- ADMP( va( "^3!revert: ^7revert aborted: reverting this %s would "
- "conflict with another buildable, use ^3!revert %s ^7to override\n",
- action, argbuf ) );
- return qfalse;
- }
- // else replace it but don't mark it ( it might have been marked before
- // but it isn't that important )
- G_SpawnRevertedBuildable( ptr, qfalse );
- break;
- default:
- // if this happens something has gone wrong
- ADMP( "^3!revert: ^7incomplete or corrupted build log entry\n" );
- /* quarantine and dispose of the log, it's dangerous
- trap_Cvar_Set( "g_buildLogMaxLength", "0" );
- G_CountBuildLog( );
- */
- return qfalse;
- }
- if( j == level.num_entities )
- {
- ADMP( va( "^3!revert: ^7could not find logged buildable #%d\n", ptr->ID ));
- prev = ptr;
- ptr = ptr->next;
- continue;
- }
- // this is similar to the buildlog stuff
- if( BG_FindUniqueTestForBuildable( ptr->buildable ) )
- article = "the";
- else if( strchr( "aeiouAEIOU", *bname ) )
- article = "an";
- else
- article = "a";
- AP( va( "print \"%s^7 reverted %s^7'%s %s of %s %s\n\"",
- ( ent ) ? G_admin_adminPrintName( ent ) : "console",
- name, strchr( "Ss", name[ strlen( name ) - 1 ] ) ? "" : "s",
- action, article, bname ) );
- matchlen++;
- // remove the reverted entry
- // ptr moves on, prev just readjusts ->next unless it is about to be
- // freed, in which case it is forced to move on too
- tmp = ptr;
- if( ptr == level.buildHistory )
- prev = level.buildHistory = ptr = ptr->next;
- else
- prev->next = ptr = ptr->next;
- G_Free( tmp );
- }
- if( ID && !reached )
- {
- ADMP( "^3!revert: ^7no buildlog entry with that ID\n" );
- return qfalse;
+ level.alienTeamLocked = lock;
}
-
- if( !matchlen )
+ else if( team == TEAM_HUMANS )
{
- ADMP( "^3!revert: ^7no log entries match those criteria\n" );
- return qfalse;
+ if( level.humanTeamLocked == lock )
+ fail = qtrue;
+ else
+ level.humanTeamLocked = lock;
}
else
{
- ADMP( va( "^3!revert: ^7reverted %d buildlog events\n", matchlen ) );
- }
-
- return qtrue;
-}
-
-void G_Unescape( char *input, char *output, int len );
-qboolean G_StringReplaceCvars( char *input, char *output, int len );
-
-qboolean G_admin_info( gentity_t *ent, int skiparg )
-{
- fileHandle_t infoFile;
- int length;
- char filename[ MAX_OSPATH ], message[ MAX_STRING_CHARS ];
- if( G_SayArgc() == 2 + skiparg )
- G_SayArgv( 1 + skiparg, filename, sizeof( filename ) );
- else if( G_SayArgc() == 1 + skiparg )
- Q_strncpyz( filename, "default", sizeof( filename ) );
- else
- {
- ADMP( "^3!info: ^7usage: ^3!info ^7(^5subject^7)\n" );
+ ADMP( va( "^3%s: ^7invalid team: '%s'\n", command, teamName ) );
return qfalse;
}
- Com_sprintf( filename, sizeof( filename ), "info/info-%s.txt", filename );
- length = trap_FS_FOpenFile( filename, &infoFile, FS_READ );
- if( length <= 0 || !infoFile )
- {
- trap_FS_FCloseFile( infoFile );
- ADMP( "^3!info: ^7no relevant information is available\n" );
- return qfalse;
- }
- else
- {
- int i;
- char *cr;
- trap_FS_Read( message, sizeof( message ), infoFile );
- if( length < sizeof( message ) )
- message[ length ] = '\0';
- else
- message[ sizeof( message ) - 1 ] = '\0';
- trap_FS_FCloseFile( infoFile );
- // strip carriage returns for windows platforms
- while( ( cr = strchr( message, '\r' ) ) )
- memmove( cr, cr + 1, strlen( cr + 1 ) + 1 );
-#define MAX_INFO_PARSE_LOOPS 100
- for( i = 0; i < MAX_INFO_PARSE_LOOPS &&
- G_StringReplaceCvars( message, message, sizeof( message ) ); i++ );
- G_Unescape( message, message, sizeof( message ) );
- if( i == MAX_INFO_PARSE_LOOPS )
- G_Printf( S_COLOR_YELLOW "WARNING: %s exceeds MAX_INFO_PARSE_LOOPS\n", filename );
- ADMP( va( "%s\n", message ) );
- return qtrue;
- }
-}
-
-void G_Unescape( char *input, char *output, int len )
-{
- // \n -> newline, \%c -> %c
- // output is terminated at output[len - 1]
- // it's OK for input to equal output, because our position in input is always
- // equal or greater than our position in output
- // however, if output is later in the same string as input, a crash is pretty
- // much inevitable
- int i, j;
- for( i = j = 0; input[i] && j + 1 < len; i++, j++ )
- {
- if( input[i] == '\\' )
- {
- if( !input[++i] )
- {
- output[j] = '\0';
- return;
- }
- else if( input[i] == 'n' )
- output[j] = '\n';
- else
- output[j] = input[i];
- }
- else
- output[j] = input[i];
- }
- output[j] = '\0';
-}
-qboolean G_StringReplaceCvars( char *input, char *output, int len )
-{
- int i, outNum = 0;
- char cvarName[ 64 ], cvarValue[ MAX_CVAR_VALUE_STRING ];
- char *outputBuffer;
- qboolean doneAnything = qfalse;
- if( len <= 0 )
- return qfalse;
- // use our own internal buffer in case output == input
- outputBuffer = G_Alloc( len );
- len -= 1; // fit in a terminator
- while( *input && outNum < len )
+ if( fail )
{
- if( *input == '\\' && input[1] && outNum < len - 1 )
- {
- outputBuffer[ outNum++ ] = *input++;
- outputBuffer[ outNum++ ] = *input++;
- }
- else if( *input == '$' )
- {
- doneAnything = qtrue;
- input++;
- if( *input == '{' )
- input++;
- for( i = 0; *input && ( isalnum( *input ) || *input == '_' ) &&
- i < 63; i++ )
- cvarName[ i ] = *input++;
- cvarName[ i ] = '\0';
- if( *input == '}' )
- input++;
- trap_Cvar_VariableStringBuffer( cvarName, cvarValue, sizeof( cvarValue ) );
- if( cvarValue[ 0 ] )
- {
- for( i = 0; cvarValue[ i ] && outNum < len; i++ )
- outputBuffer[ outNum++ ] = cvarValue[ i ];
- }
- }
- else
- outputBuffer[ outNum++ ] = *input++;
- }
- outputBuffer[ outNum ] = '\0';
- Q_strncpyz( output, outputBuffer, len );
- G_Free( outputBuffer );
- return doneAnything;
-}
-
-/*
-================
- G_admin_print
+ ADMP( va( "^3%s: ^7the %s team is %s locked\n",
+ command, BG_TeamName( team ), lock ? "already" : "not currently" ) );
- This function facilitates the ADMP define. ADMP() is similar to CP except
- that it prints the message to the server console if ent is not defined.
-================
-*/
-void G_admin_print( gentity_t *ent, char *m )
-{
- if( ent )
- trap_SendServerCommand( ent - level.gentities, va( "print \"%s\"", m ) );
- else
- {
- char m2[ MAX_STRING_CHARS ];
- if( !trap_Cvar_VariableIntegerValue( "com_ansiColor" ) )
- {
- G_DecolorString( m, m2 );
- G_Printf( m2 );
- }
- else
- G_Printf( m );
+ return qfalse;
}
-}
-void G_admin_buffer_begin()
-{
- g_bfb[ 0 ] = '\0';
-}
+ admin_log( BG_TeamName( team ) );
+ AP( va( "print \"^3%s: ^7the %s team has been %slocked by %s\n\"",
+ command, BG_TeamName( team ), lock ? "" : "un",
+ ent ? ent->client->pers.netname : "console" ) );
-void G_admin_buffer_end( gentity_t *ent )
-{
- ADMP( g_bfb );
+ return qtrue;
}
-void G_admin_buffer_print( gentity_t *ent, char *m )
+qboolean G_admin_builder( gentity_t *ent )
{
- // 1022 - strlen("print 64 \"\"") - 1
- if( strlen( m ) + strlen( g_bfb ) >= 1009 )
- {
- ADMP( g_bfb );
- g_bfb[ 0 ] = '\0';
- }
- Q_strcat( g_bfb, sizeof( g_bfb ), m );
-}
+ vec3_t forward, right, up;
+ vec3_t start, end, dist;
+ trace_t tr;
+ gentity_t *traceEnt;
+ buildLog_t *log;
+ int i;
+ qboolean buildlog;
+ char logid[ 20 ] = {""};
-
-void G_admin_cleanup()
-{
- int i = 0;
-
- for( i = 0; i < MAX_ADMIN_LEVELS && g_admin_levels[ i ]; i++ )
- {
- G_Free( g_admin_levels[ i ] );
- g_admin_levels[ i ] = NULL;
- }
- for( i = 0; i < MAX_ADMIN_ADMINS && g_admin_admins[ i ]; i++ )
- {
- G_Free( g_admin_admins[ i ] );
- g_admin_admins[ i ] = NULL;
- }
- for( i = 0; i < MAX_ADMIN_BANS && g_admin_bans[ i ]; i++ )
- {
- G_Free( g_admin_bans[ i ] );
- g_admin_bans[ i ] = NULL;
- }
- for( i = 0; i < MAX_ADMIN_COMMANDS && g_admin_commands[ i ]; i++ )
- {
- G_Free( g_admin_commands[ i ] );
- g_admin_commands[ i ] = NULL;
- }
-}
-
-qboolean G_admin_L0(gentity_t *ent, int skiparg ){
- int pids[ MAX_CLIENTS ];
- char name[ MAX_NAME_LENGTH ] = {""};
- char testname[ MAX_NAME_LENGTH ] = {""};
- char err[ MAX_STRING_CHARS ];
- qboolean numeric = qtrue;
- int i;
- int id = -1;
- gentity_t *vic;
-
- if( G_SayArgc() < 2 + skiparg )
+ if( !ent )
{
- ADMP( "^3!L0: ^7usage: !L0 [name|slot#|admin#]\n" );
+ ADMP( "^3builder: ^7console can't aim.\n" );
return qfalse;
}
- G_SayArgv( 1 + skiparg, testname, sizeof( testname ) );
- G_SanitiseString( testname, name, sizeof( name ) );
- for( i = 0; i < sizeof( name ) && name[ i ] ; i++ )
- {
- if( name[ i ] < '0' || name[ i ] > '9' )
- {
- numeric = qfalse;
- break;
- }
- }
- if( numeric )
- {
- id = atoi( name );
- }
+ buildlog = G_admin_permission( ent, "buildlog" );
+
+ AngleVectors( ent->client->ps.viewangles, forward, right, up );
+ if( ent->client->pers.teamSelection != TEAM_NONE &&
+ ent->client->sess.spectatorState == SPECTATOR_NOT )
+ CalcMuzzlePoint( ent, forward, right, up, start );
else
- {
- if( G_ClientNumbersFromString( name, pids ) != 1 )
- {
- G_MatchOnePlayer( pids, err, sizeof( err ) );
- ADMP( va( "^3!L0: ^7%s\n", err ) );
- return qfalse;
- }
- id = pids[ 0 ];
- }
+ VectorCopy( ent->client->ps.origin, start );
+ VectorMA( start, 1000, forward, end );
- if (id >= 0 && id < level.maxclients)
+ trap_Trace( &tr, start, NULL, NULL, end, ent->s.number, MASK_PLAYERSOLID );
+ traceEnt = &g_entities[ tr.entityNum ];
+ if( tr.fraction < 1.0f && ( traceEnt->s.eType == ET_BUILDABLE ) )
{
- vic = &g_entities[ id ];
- if( !vic || !(vic->client) || vic->client->pers.connected != CON_CONNECTED )
+ if( !buildlog &&
+ ent->client->pers.teamSelection != TEAM_NONE &&
+ ent->client->pers.teamSelection != traceEnt->buildableTeam )
{
- ADMP( "^3!L0:^7 no one connected by that slot number\n" );
+ ADMP( "^3builder: ^7structure not owned by your team\n" );
return qfalse;
}
- if( G_admin_level( vic ) != 1 )
+ if( buildlog )
{
- ADMP( "^3!L0:^7 intended victim is not level 1\n" );
- return qfalse;
- }
- }
- else if (id >= MAX_CLIENTS && id < MAX_CLIENTS + MAX_ADMIN_ADMINS
- && g_admin_admins[ id - MAX_CLIENTS ] )
- {
- if( g_admin_admins[ id - MAX_CLIENTS ]->level != 1 )
- {
- ADMP( "^3!L0:^7 intended victim is not level 1\n" );
- return qfalse;
+ for( i = 0 ; buildlog && i < level.numBuildLogs; i++ )
+ {
+ log = &level.buildLog[ ( level.buildId - i - 1 ) % MAX_BUILDLOG ];
+ if( log->fate != BF_CONSTRUCT || traceEnt->s.modelindex != log->modelindex )
+ continue;
+
+ VectorSubtract( traceEnt->s.pos.trBase, log->origin, dist );
+ if( VectorLengthSquared( dist ) < 2.0f )
+ Com_sprintf( logid, sizeof( logid ), ", buildlog #%d",
+ MAX_CLIENTS + level.buildId - i - 1 );
+ }
}
+
+ ADMP( va( "^3builder: ^7%s%s%s^7%s\n",
+ BG_Buildable( traceEnt->s.modelindex )->humanName,
+ traceEnt->builtBy ? " built by " : "",
+ traceEnt->builtBy ?
+ traceEnt->builtBy->name[ traceEnt->builtBy->nameOffset ] :
+ "",
+ buildlog ? ( logid[ 0 ] ? logid : ", not in buildlog" ) : "" ) );
}
else
- {
- ADMP( "^3!L0:^7 no match. use !listplayers or !listadmins to "
- "find an appropriate number to use instead of name.\n" );
- return qfalse;
- }
-
- trap_SendConsoleCommand( EXEC_APPEND, va( "!setlevel %d 0;", id ) );
+ ADMP( "^3builder: ^7no structure found under crosshair\n" );
return qtrue;
}
-qboolean G_admin_L1(gentity_t *ent, int skiparg ){
- int pids[ MAX_CLIENTS ];
- char name[ MAX_NAME_LENGTH ], *reason, err[ MAX_STRING_CHARS ];
- int minargc;
-
- minargc = 2 + skiparg;
-
- if( G_SayArgc() < minargc )
- {
- ADMP( "^3!L1: ^7usage: !L1 [name]\n" );
- return qfalse;
- }
- G_SayArgv( 1 + skiparg, name, sizeof( name ) );
- reason = G_SayConcatArgs( 2 + skiparg );
- if( G_ClientNumbersFromString( name, pids ) != 1 )
- {
- G_MatchOnePlayer( pids, err, sizeof( err ) );
- ADMP( va( "^3!L1: ^7%s\n", err ) );
- return qfalse;
- }
- if( G_admin_level(&g_entities[ pids[ 0 ] ] )>0 )
- {
- ADMP( "^3!L1: ^7Sorry, but that person is already higher than level 0.\n" );
- return qfalse;
- }
-
- trap_SendConsoleCommand( EXEC_APPEND,va( "!setlevel %d 1;", pids[ 0 ] ) );
- return qtrue;
-}
-
-qboolean G_admin_invisible( gentity_t *ent, int skiparg )
+qboolean G_admin_pause( gentity_t *ent )
{
- if( !ent )
- {
- ADMP( "!invisible: console can not become invisible.\n" );
- return qfalse;
- }
-
- if ( ent->client->sess.invisible != qtrue )
+ if( !level.pausedTime )
{
- // Make the player invisible
- G_ChangeTeam( ent, PTE_NONE );
- ent->client->sess.invisible = qtrue;
- ClientUserinfoChanged( ent->client->pers.connection->clientNum, qfalse );
- G_admin_namelog_update( ent->client, qtrue );
- trap_SendServerCommand( -1, va( "print \"%s" S_COLOR_WHITE " disconnected\n\"", ent->client->pers.netname ) );
+ AP( va( "print \"^3pause: ^7%s^7 paused the game.\n\"",
+ ( ent ) ? ent->client->pers.netname : "console" ) );
+ level.pausedTime = 1;
+ trap_SendServerCommand( -1, "cp \"The game has been paused. Please wait.\"" );
}
else
{
- // Make the player visible
- ent->client->sess.invisible = qfalse;
- ClientUserinfoChanged( ent->client->pers.connection->clientNum, qfalse );
- G_admin_namelog_update( ent->client, qfalse );
- trap_SendServerCommand( -1, va( "print \"%s" S_COLOR_WHITE " connected\n\"", ent->client->pers.netname ) );
- trap_SendServerCommand( -1, va( "print \"%s" S_COLOR_WHITE " entered the game\n\"", ent->client->pers.netname ) );
- }
- return qtrue;
-}
+ // Prevent accidental pause->unpause race conditions by two admins
+ if( level.pausedTime < 1000 )
+ {
+ ADMP( "^3pause: ^7Unpausing so soon assumed accidental and ignored.\n" );
+ return qfalse;
+ }
-qboolean G_admin_decon( gentity_t *ent, int skiparg )
-{
- int i = 0, j = 0, repeat = 24, pids[ MAX_CLIENTS ], len, matchlen = 0;
- pTeam_t team = PTE_NONE;
- qboolean force = qfalse, reached = qfalse;
- gentity_t *builder = NULL, *targ;
- buildHistory_t *ptr, *tmp, *mark, *prev;
- vec3_t dist;
- char arg[ 64 ], err[ MAX_STRING_CHARS ], *name, *bname, *action, *article, *reason;
- len = G_CountBuildLog( );
-
- if( !len )
- {
- ADMP( "^3!decon: ^7no build log found, aborting...\n" );
- return qfalse;
- }
+ AP( va( "print \"^3pause: ^7%s^7 unpaused the game (Paused for %d sec) \n\"",
+ ( ent ) ? ent->client->pers.netname : "console",
+ (int) ( (float) level.pausedTime / 1000.0f ) ) );
+ trap_SendServerCommand( -1, "cp \"The game has been unpaused!\"" );
- if( G_SayArgc( ) < 2 + skiparg )
- {
- ADMP( "^3!decon: ^7usage: !decon (^5name|num^7)\n" );
- return qfalse;
+ level.pausedTime = 0;
}
- G_SayArgv( 1 + skiparg, arg, sizeof( arg ) );
- if( G_ClientNumbersFromString( arg, pids ) != 1 )
- {
- G_MatchOnePlayer( pids, err, sizeof( err ) );
- ADMP( va( "^3!decon: ^7%s\n", err ) );
- return qfalse;
- }
+ return qtrue;
+}
- builder = g_entities + *pids;
- if( builder->client->sess.invisible == qtrue )
- {
- ADMP( va( "^3!decon: ^7no connected player by the name or slot #\n" ) );
- return qfalse;
+static char *fates[] =
+{
+ "^2built^7",
+ "^3deconstructed^7",
+ "^7replaced^7",
+ "^3destroyed^7",
+ "^1TEAMKILLED^7",
+ "^7unpowered^7",
+ "removed"
+};
+qboolean G_admin_buildlog( gentity_t *ent )
+{
+ char search[ MAX_NAME_LENGTH ] = {""};
+ char s[ MAX_NAME_LENGTH ] = {""};
+ char n[ MAX_NAME_LENGTH ];
+ char stamp[ 8 ];
+ int id = -1;
+ int printed = 0;
+ int time;
+ int start = MAX_CLIENTS + level.buildId - level.numBuildLogs;
+ int i = 0, j;
+ buildLog_t *log;
+
+ if( !level.buildId )
+ {
+ ADMP( "^3buildlog: ^7log is empty\n" );
+ return qtrue;
}
- if( !admin_higher( ent, builder ) )
+ if( trap_Argc() == 3 )
{
- ADMP( "^3!decon: ^7sorry, but your intended victim has a higher admin"
- "level than you\n");
- return qfalse;
+ trap_Argv( 2, search, sizeof( search ) );
+ start = atoi( search );
}
-
- for( i = 0, ptr = prev = level.buildHistory; repeat > 0; repeat--, j = 0 )
+ if( trap_Argc() > 1 )
{
- if( !ptr )
- break;
- if( builder && builder != ptr->ent )
- {
- // team doesn't match, so skip this ptr and reset prev
- prev = ptr;
- ptr = ptr->next;
- // we don't want to count this one so counteract the decrement by the for
- repeat++;
- continue;
- }
- // get the ent's current or last recorded name
- if( ptr->ent )
- {
- if( ptr->ent->client )
- name = ptr->ent->client->pers.netname;
- else
- name = "<world>"; // non-client actions
- }
- else
- name = ptr->name;
- bname = BG_FindHumanNameForBuildable( ptr->buildable );
- action = "";
- switch( ptr->fate )
+ trap_Argv( 1, search, sizeof( search ) );
+ for( i = search[ 0 ] == '-'; isdigit( search[ i ] ); i++ );
+ if( i && !search[ i ] )
{
- case BF_BUILT:
- prev = ptr;
- ptr = ptr->next;
- repeat++;
- continue;
- case BF_DESTROYED:
- prev = ptr;
- ptr = ptr->next;
- repeat++;
- case BF_DECONNED:
- if( !action[0] ) action = "^3deconstruction^7";
- case BF_TEAMKILLED:
- if( !action[0] ) action = "^1TEAMKILL^7";
- // if we're not overriding and the replacement can't fit, as before
- if( !G_RevertCanFit( ptr ) )
- {
- prev = ptr;
- ptr = ptr->next;
- repeat++;
- continue;
- }
- // else replace it but don't mark it ( it might have been marked before
- // but it isn't that important )
- G_SpawnRevertedBuildable( ptr, qfalse );
- break;
- default:
- // if this happens something has gone wrong
- ADMP( "^3!decon: ^7incomplete or corrupted build log entry\n" );
- /* quarantine and dispose of the log, it's dangerous
- trap_Cvar_Set( "g_buildLogMaxLength", "0" );
- G_CountBuildLog( );
- */
+ id = atoi( search );
+ if( trap_Argc() == 2 && ( id < 0 || id >= MAX_CLIENTS ) )
+ {
+ start = id;
+ id = -1;
+ }
+ else if( id < 0 || id >= MAX_CLIENTS ||
+ level.clients[ id ].pers.connected != CON_CONNECTED )
+ {
+ ADMP( "^3buildlog: ^7invalid client id\n" );
return qfalse;
+ }
}
- // this is similar to the buildlog stuff
- if( BG_FindUniqueTestForBuildable( ptr->buildable ) )
- article = "the";
- else if( strchr( "aeiouAEIOU", *bname ) )
- article = "an";
else
- article = "a";
- AP( va( "print \"%s^7 reverted %s^7'%s %s of %s %s\n\"",
- ( ent ) ? G_admin_adminPrintName( ent ) : "console",
- name, strchr( "Ss", name[ strlen( name ) - 1 ] ) ? "" : "s",
- action, article, bname ) );
- matchlen++;
- // remove the reverted entry
- // ptr moves on, prev just readjusts ->next unles it is about to be
- // freed, in which case it is forced to move on too
- tmp = ptr;
- if( ptr == level.buildHistory )
- prev = level.buildHistory = ptr = ptr->next;
- else
- prev->next = ptr = ptr->next;
- G_Free( tmp );
+ G_SanitiseString( search, s, sizeof( s ) );
}
+ else
+ start = MAX( -MAX_ADMIN_LISTITEMS, -level.buildId );
- if( !matchlen )
+ if( start < 0 )
+ start = MAX( level.buildId - level.numBuildLogs, start + level.buildId );
+ else
+ start -= MAX_CLIENTS;
+ if( start < level.buildId - level.numBuildLogs || start >= level.buildId )
{
- ADMP( "^3!decopn: ^7This user doesn't seem to have deconned anything...\n" );
+ ADMP( "^3buildlog: ^7invalid build ID\n" );
return qfalse;
}
- ADMP( va( "^3!decon: ^7reverted %d buildlog events\n", matchlen ) );
- admin_create_ban( ent,
- builder->client->pers.netname,
- builder->client->pers.guid,
- builder->client->pers.ip, G_admin_parse_time( g_deconBanTime.string ),
- ( *reason ) ? reason : "^1Decon" );
- if( g_admin.string[ 0 ] )
- admin_writeconfig();
-
- trap_SendServerCommand( pids[ 0 ],
- va( "disconnect \"You have been kicked.\n%s^7\nreason:\n%s\n%s\"",
- ( ent ) ? va( "admin:\n%s", G_admin_adminPrintName( ent ) ) : "admin\nconsole",
- ( *reason ) ? reason : "^1Decon" ) );
-
- trap_DropClient( pids[ 0 ], va( "kicked%s^7, reason: %s",
- ( ent ) ? va( " by %s", G_admin_adminPrintName( ent ) ) : " by console",
- ( *reason ) ? reason : "^1Decon" ) );
-
- return qtrue;
-}
+ if( ent && ent->client->pers.teamSelection != TEAM_NONE )
+ trap_SendServerCommand( -1,
+ va( "print \"^3buildlog: ^7%s^7 requested a log of recent building activity\n\"",
+ ent->client->pers.netname ) );
-qboolean G_admin_setdevmode( gentity_t *ent, int skiparg )
-{
- char str[ 5 ];
-
- if( G_SayArgc() != 2 + skiparg )
- {
- ADMP( "^3!setdevmode: ^7usage: !setdevmode [on|off]\n" );
- return qfalse;
- }
- G_SayArgv( 1 + skiparg, str, sizeof( str ) );
-
- if( !Q_stricmp( str, "on" ) )
+ ADMBP_begin();
+ for( i = start; i < level.buildId && printed < MAX_ADMIN_LISTITEMS; i++ )
{
- if( g_cheats.integer )
+ log = &level.buildLog[ i % MAX_BUILDLOG ];
+ if( id >= 0 && id < MAX_CLIENTS )
{
- ADMP( "^3!setdevmode: ^7developer mode is already on\n" );
- return qfalse;
+ if( log->actor != level.clients[ id ].pers.namelog )
+ continue;
}
- trap_Cvar_Set( "sv_cheats", "1" );
- trap_Cvar_Update( &g_cheats );
- AP( va( "print \"^3!setdevmode: ^7%s ^7has switched developer mode on\n\"",
- ent ? G_admin_adminPrintName( ent ) : "console" ) );
- }
- else if( !Q_stricmp( str, "off" ) )
- {
- if( !g_cheats.integer )
+ else if( s[ 0 ] )
{
- ADMP( "^3!setdevmode: ^7developer mode is already off\n" );
- return qfalse;
+ if( !log->actor )
+ continue;
+ for( j = 0; j < MAX_NAMELOG_NAMES && log->actor->name[ j ][ 0 ]; j++ )
+ {
+ G_SanitiseString( log->actor->name[ j ], n, sizeof( n ) );
+ if( strstr( n, s ) )
+ break;
+ }
+ if( j >= MAX_NAMELOG_NAMES || !log->actor->name[ j ][ 0 ] )
+ continue;
}
- trap_Cvar_Set( "sv_cheats", "0" );
- trap_Cvar_Update( &g_cheats );
- AP( va( "print \"^3!setdevmode: ^7%s ^7has switched developer mode off\n\"",
- ent ? G_admin_adminPrintName( ent ) : "console" ) );
- }
- else
- {
- ADMP( "^3!setdevmode: ^7usage: !setdevmode [on|off]\n" );
- return qfalse;
- }
-
+ printed++;
+ time = ( log->time - level.startTime ) / 1000;
+ Com_sprintf( stamp, sizeof( stamp ), "%3d:%02d", time / 60, time % 60 );
+ ADMBP( va( "^2%c^7%-3d %s %s^7%s%s%s %s%s%s\n",
+ log->actor && log->fate != BF_REPLACE && log->fate != BF_UNPOWER ?
+ '*' : ' ',
+ i + MAX_CLIENTS,
+ log->actor && ( log->fate == BF_REPLACE || log->fate == BF_UNPOWER ) ?
+ " \\_" : stamp,
+ BG_Buildable( log->modelindex )->humanName,
+ log->builtBy && log->fate != BF_CONSTRUCT ?
+ " (built by " :
+ "",
+ log->builtBy && log->fate != BF_CONSTRUCT ?
+ log->builtBy->name[ log->builtBy->nameOffset ] :
+ "",
+ log->builtBy && log->fate != BF_CONSTRUCT ?
+ "^7)" :
+ "",
+ fates[ log->fate ],
+ log->actor ? " by " : "",
+ log->actor ?
+ log->actor->name[ log->actor->nameOffset ] :
+ "" ) );
+ }
+ ADMBP( va( "^3buildlog: ^7showing %d build logs %d - %d of %d - %d. %s\n",
+ printed, start + MAX_CLIENTS, i + MAX_CLIENTS - 1,
+ level.buildId + MAX_CLIENTS - level.numBuildLogs,
+ level.buildId + MAX_CLIENTS - 1,
+ i < level.buildId ? va( "run 'buildlog %s%s%d' to see more",
+ search, search[ 0 ] ? " " : "", i + MAX_CLIENTS ) : "" ) );
+ ADMBP_end();
return qtrue;
}
-qboolean G_admin_hstage( gentity_t *ent, int skiparg )
+qboolean G_admin_revert( gentity_t *ent )
{
+ char arg[ MAX_TOKEN_CHARS ];
+ char time[ MAX_DURATION_LENGTH ];
+ int id;
+ buildLog_t *log;
- char lvl_chr[ MAX_STRING_CHARS ];
- int minargc;
- int lvl;
-
-
- minargc = 2 + skiparg;
-
- if( G_SayArgc() < minargc )
+ if( trap_Argc() != 2 )
{
- ADMP( "^3!hstage: ^7hstage: !hstage [#]\n" );
+ ADMP( "^3revert: ^7usage: revert [id]\n" );
return qfalse;
}
- G_SayArgv( 1 + skiparg, lvl_chr, sizeof( lvl_chr ) );
-
- lvl = atoi(lvl_chr);
-
- lvl -= 1;
- trap_SendConsoleCommand( EXEC_APPEND, va( "g_humanStage %i", lvl ) );
-
- return qtrue;
-
-}
-
-qboolean G_admin_astage( gentity_t *ent, int skiparg )
-{
-
- char lvl_chr[ MAX_STRING_CHARS ];
- int minargc;
- int lvl;
-
-
- minargc = 2 + skiparg;
-
- if( G_SayArgc() < minargc )
+ trap_Argv( 1, arg, sizeof( arg ) );
+ id = atoi( arg ) - MAX_CLIENTS;
+ if( id < level.buildId - level.numBuildLogs || id >= level.buildId )
{
- ADMP( "^3!astage: ^7astage: !astage [#]\n" );
+ ADMP( "^3revert: ^7invalid id\n" );
return qfalse;
}
- G_SayArgv( 1 + skiparg, lvl_chr, sizeof( lvl_chr ) );
-
- lvl = atoi(lvl_chr);
-
- lvl -= 1;
- trap_SendConsoleCommand( EXEC_APPEND, va( "g_alienStage %i", lvl ) );
-
- return qtrue;
-
-}
-
-qboolean G_admin_bubble( gentity_t *ent, int skiparg )
-{
- int pids[ MAX_CLIENTS ];
- char name[ MAX_NAME_LENGTH ], err[ MAX_STRING_CHARS ];
- gentity_t *vic;
-
- if(g_Bubbles.integer)
- {
- if( G_SayArgc() < 2 + skiparg )
- {
- ADMP( "^3!bubble: ^7usage: !bubble [name|slot#]\n" );
- return qfalse;
- }
- G_SayArgv( 1 + skiparg, name, sizeof( name ) );
- if( G_ClientNumbersFromString( name, pids ) != 1 )
- {
- G_MatchOnePlayer( pids, err, sizeof( err ) );
- ADMP( va( "^3!bubble: ^7%s\n", err ) );
- return qfalse;
- }
- vic = &g_entities[ pids[ 0 ] ];
- if(vic->client->sess.invisible == qtrue)
- {
- ADMP( va( "^3!bubble: ^7no connected player by that name or slot #\n" ) );
- return qfalse;
- }
- if( !admin_higher( ent, &g_entities[ pids[ 0 ] ] ) )
- {
- ADMP( "^3!bubble: ^7sorry, but your intended victim has a higher admin"
- " level than you\n" );
- return qfalse;
- }
-
-
- if( vic->client->pers.bubbleTime )
- vic->client->pers.bubbleTime = 0;
- else
- vic->client->pers.bubbleTime = level.time + 500;
-
- AP( va( "print \"^3!bubble: ^7bubbles %s for %s^7 by %s\n\"",
- ( vic->client->pers.bubbleTime ) ? "enabled" : "disabled",
- vic->client->pers.netname,
- ( ent ) ? G_admin_adminPrintName( ent ) : "console" ) );
- }
- else
+ log = &level.buildLog[ id % MAX_BUILDLOG ];
+ if( !log->actor || log->fate == BF_REPLACE || log->fate == BF_UNPOWER )
{
- ADMP( "^3!bubble: ^7sorry, but bubbles have been disabled on this server.\n" );
- return qfalse;
+ // fixme: then why list them with an id # in build log ? - rez
+ ADMP( "^3revert: ^7you can only revert direct player actions, "
+ "indicated by ^2* ^7in buildlog\n" );
+ return qfalse;
}
- return qtrue;
-}
-
-qboolean G_admin_scrim(gentity_t *ent, int skiparg )
-{
- char state[5];
-
- if( G_SayArgc() < 2 + skiparg )
- {
- ADMP( "^3!scrim: ^7usage: !scrim [on|off]\n" );
- return qfalse;
- }
-
- G_SayArgv( 1 + skiparg, state, sizeof( state ) );
-
- if( !Q_stricmp(state, "on") )
- {
- if( g_scrimMode.integer != 0 )
- {
- ADMP( "^3!scrim: ^7scrim mode is already enabled.\n" );
- return qfalse;
- }
- AP( va( "print \"^3!scrim: ^7%s ^7turned scrim mode ^2on^7\n\"", ( ent ) ? G_admin_adminPrintName( ent ) : "console" ) );
- trap_Cvar_Set( "g_scrimMode", "1" );
- }
- else if( !Q_stricmp(state, "off") )
- {
- if( g_scrimMode.integer == 0 )
- {
- ADMP( "^3!scrim: ^7scrim mode is already disabled.\n" );
- return qfalse;
- }
- AP( va( "print \"^3!scrim: ^7%s ^7turned scrim mode ^1off^7\n\"", ( ent ) ? G_admin_adminPrintName( ent ) : "console" ) );
- trap_Cvar_Set( "g_scrimMode", "0" );
-
- } else {
- ADMP( "^3!scrim: ^7usage: !scrim [on|off]\n" );
- return qfalse;
- }
-
+ G_admin_duration( ( level.time - log->time ) / 1000, time,
+ sizeof( time ) );
+ admin_log( arg );
+ AP( va( "print \"^3revert: ^7%s^7 reverted %d %s over the past %s\n\"",
+ ent ? ent->client->pers.netname : "console",
+ level.buildId - id,
+ ( level.buildId - id ) > 1 ? "changes" : "change",
+ time ) );
+ G_BuildLogRevert( id );
return qtrue;
}
-qboolean G_admin_give(gentity_t *ent, int skiparg)
-{
- char arg_name_raw[MAX_NAME_LENGTH];
- char arg_name[MAX_NAME_LENGTH];
- char arg_amount[30];
- int target_id, amount;
- gentity_t *target;
- const char *currency;
-
- if (G_SayArgc() < 3 + skiparg) {
- ADMP("^3!give: ^7usage: !give [player] [amount]\n");
- return qfalse;
- }
-
- G_SayArgv(1 + skiparg, arg_name_raw, sizeof(arg_name_raw));
- G_SanitiseString(arg_name_raw, arg_name, sizeof(arg_name));
-
- if (is_numeric(arg_name)) {
- target_id = atoi(arg_name);
-
- if (target_id < 0 || target_id >= MAX_CLIENTS) {
- ADMP(va("^3!give: ^7invalid client number\n"));
- return qfalse;
- }
- } else {
- int pids[ MAX_CLIENTS ];
-
- if (G_ClientNumbersFromString(arg_name, pids) != 1) {
- char error[MAX_STRING_CHARS];
-
- G_MatchOnePlayer(pids, error, sizeof(error));
- ADMP(va("^3!give: ^7%s\n", error));
- return qfalse;
- }
-
- target_id = pids[0];
- }
-
-
- target = g_entities + target_id;
-
- if (!target->client ||
- target->client->pers.connected != CON_CONNECTED) {
- invalid_target:
- ADMP("^3!give: ^7invalid target\n");
- return qfalse;
- }
-
- G_SayArgv(2 + skiparg, arg_amount, sizeof(arg_amount));
- amount = atoi(arg_amount);
-
- switch (target->client->pers.teamSelection) {
- case PTE_ALIENS:
- if (amount < -9 || amount > 9) {
- too_big:
- ADMP("^3!give: ^7amount is too big\n");
- return qfalse;
- }
-
- currency = "evo";
- break;
-
- case PTE_HUMANS:
- if (amount < -2000 || amount > 2000)
- goto too_big;
-
- currency = "credit";
- break;
-
- default:
- goto invalid_target;
- }
-
- G_AddCreditToClient(target->client, amount, qtrue);
- AP(va("print \"^3!give: ^7%s^7 was given %i %s%s by ^7%s^7\n\"",
- target->client->pers.netname, amount, currency,
- (abs(amount) != 1 ? "s" : ""),
- ent ? G_admin_adminPrintName(ent) : "console"));
-
- return qtrue;
-}
-
-extern mapRotations_t mapRotations;
+/*
+================
+ G_admin_print
-qboolean G_admin_setrotation(gentity_t *ent, int skiparg)
+ This function facilitates the ADMP define. ADMP() is similar to CP except
+ that it prints the message to the server console if ent is not defined.
+================
+*/
+void G_admin_print( gentity_t *ent, const char *m )
{
- char new_rotation[MAX_NAME_LENGTH];
- int i;
-
- if (G_SayArgc() < 2 + skiparg)
- {
- ADMP("^3!setrotation: ^7usage: !setrotation [rotation]\n");
- ADMP("Available rotations:\n");
- goto rotationlist;
- }
-
- G_SayArgv(1 + skiparg, new_rotation, sizeof(new_rotation));
-
- for( i = 0; i < mapRotations.numRotations; i++ )
- {
- if( Q_stricmp( mapRotations.rotations[ i ].name, new_rotation ) == 0 )
- {
- G_StartMapRotation(new_rotation, qfalse);
- trap_SendServerCommand( -1, va("print \"^3!setrotation: ^7rotation ^3%s ^7was started by %s",
- new_rotation, ent ? G_admin_adminPrintName(ent) : "console"));
- return qtrue;
- }
- }
- ADMP("^3!setrotation: ^7rotation not found. Available rotations:\n");
- goto rotationlist;
- rotationlist:
+ if( ent )
+ trap_SendServerCommand( ent - level.gentities, va( "print \"%s\"", m ) );
+ else
{
- for( i = 0; i < mapRotations.numRotations; i++ )
+ char m2[ MAX_STRING_CHARS ];
+ if( !trap_Cvar_VariableIntegerValue( "com_ansiColor" ) )
{
- ADMP(va(" %s\n", mapRotations.rotations[ i ].name));
+ G_DecolorString( m, m2, sizeof( m2 ) );
+ trap_Print( m2 );
}
- ADMP(va("Number of available rotations: ^3%d\n", mapRotations.numRotations));
+ else
+ trap_Print( m );
}
- return qfalse;
}
-qboolean G_admin_versions(gentity_t *ent, int skiparg)
+void G_admin_buffer_begin( void )
{
- int i;
-
- ADMBP_begin();
-
- for (i = 0; i < level.maxclients; i++) {
- gclient_t *client = level.clients + i;
- char userinfo[ MAX_INFO_STRING ], *p;
-
- if (client->pers.connected == CON_DISCONNECTED)
- continue;
-
- ADMBP(va("%02i ", i));
-
- trap_GetUserinfo(i, userinfo, sizeof(userinfo));
- p = Info_ValueForKey(userinfo, "version");
-
- if (p[0])
- ADMBP(va("'%s'\n", p));
- else {
- p = Info_ValueForKey(userinfo, "cl_voip");
-
- if (p[0])
- ADMBP("probably GPP or newer\n");
- else
- ADMBP("probably stock 1.1\n");
- }
- }
-
- ADMBP_end();
- return qtrue;
-}
-
-static int calc_ff_pct(statsCounters_t *sc) {
- if (sc->dmgdone + sc->structdmgdone <= 0) {
- if (sc->ffdmgdone <= 0)
- return 0;
- else
- return 100;
- } // else {
- // return round((float)sc->ffdmgdone / (sc->ffdmgdone + sc->dmgdone + sc->structdmgdone) * 100);
- // }
+ g_bfb[ 0 ] = '\0';
}
-qboolean G_admin_showff(gentity_t *ent, int skiparg)
+void G_admin_buffer_end( gentity_t *ent )
{
- char arg_name_raw[MAX_NAME_LENGTH];
- char arg_name[MAX_NAME_LENGTH];
- int target_id, ffpct;
- gentity_t *target;
- statsCounters_t *sc;
-
- if (G_SayArgc() == 1 + skiparg) {
- int i;
- char team[4];
- gclient_t *client;
-
- ADMBP_begin();
- ADMBP("^3!showff:^7 friendly fire damage percentage for all connected players\n");
-
- for (i = 0; i < level.maxclients; i++) {
- client = &level.clients[i];
-
- if (client->pers.connected != CON_CONNECTED)
- continue;
-
- if (client->pers.teamSelection == PTE_HUMANS)
- Com_sprintf( team, sizeof( team ), "^4H", team);
- else if (client->pers.teamSelection == PTE_ALIENS)
- Com_sprintf( team, sizeof( team ), "^1A", team);
- else
- Com_sprintf( team, sizeof( team ), "^3S", team);
-
- ffpct = calc_ff_pct(&client->pers.statscounters);
- ADMBP(va("%2d %s ^1%3d%% ^7%s^7\n", i, team, ffpct, client->pers.netname));
- }
-
- ADMBP("^7for detailed information, use ^3!showff player|slot^7\n");
- ADMBP_end();
- return qtrue;
- }
-
- G_SayArgv(1 + skiparg, arg_name_raw, sizeof(arg_name_raw));
- G_SanitiseString(arg_name_raw, arg_name, sizeof(arg_name));
-
- if (is_numeric(arg_name)) {
- target_id = atoi(arg_name);
-
- if (target_id < 0 || target_id >= MAX_CLIENTS) {
- ADMP(va("^3!showff: ^7invalid client number\n"));
- return qfalse;
- }
- } else {
- int pids[MAX_CLIENTS];
-
- if (G_ClientNumbersFromString(arg_name, pids) != 1) {
- char error[MAX_STRING_CHARS];
-
- G_MatchOnePlayer(pids, error, sizeof(error));
- ADMP(va("^3!showff: ^7%s\n", error));
- return qfalse;
- }
-
- target_id = pids[0];
- }
-
- target = g_entities + target_id;
- sc = &target->client->pers.statscounters;
- ffpct = calc_ff_pct(sc);
-
- ADMP(va("^3!showff: ^7detailed FF information for %s^7:\n",
- target->client->pers.netname));
- ADMP(va("^7damage to: Enemies: ^1%d^7, structures: ^1%d^7, friendlies: ^1%d\n",
- sc->dmgdone, sc->structdmgdone, sc->ffdmgdone));
- ADMP(va("dealt ^1%d%%^7 of their total damage to the team\n", ffpct));
-
- return qtrue;
+ ADMP( g_bfb );
}
-void G_admin_tklog_cleanup( void )
+void G_admin_buffer_print( gentity_t *ent, const char *m )
{
- int i;
-
- for( i = 0; i < MAX_ADMIN_TKLOGS && g_admin_tklog[ i ]; i++ )
+ // 1022 - strlen("print 64 \"\"") - 1
+ if( strlen( m ) + strlen( g_bfb ) >= 1009 )
{
- G_Free( g_admin_tklog[ i ] );
- g_admin_tklog[ i ] = NULL;
+ ADMP( g_bfb );
+ g_bfb[ 0 ] = '\0';
}
-
- admin_tklog_index = 0;
+ Q_strcat( g_bfb, sizeof( g_bfb ), m );
}
-void G_admin_tklog_log( gentity_t *attacker, gentity_t *victim, int meansOfDeath )
-{
- g_admin_tklog_t *tklog;
- int previous;
- int count = 1;
-
- if( !attacker )
- return;
-
- previous = admin_tklog_index - 1;
- if( previous < 0 )
- previous = MAX_ADMIN_TKLOGS - 1;
-
- if( g_admin_tklog[ previous ] )
- count = g_admin_tklog[ previous ]->id + 1;
- if( g_admin_tklog[ admin_tklog_index ] )
- tklog = g_admin_tklog[ admin_tklog_index ];
- else
- tklog = G_Alloc( sizeof( g_admin_tklog_t ) );
-
- memset( tklog, 0, sizeof( g_admin_tklog_t ) );
- tklog->id = count;
- tklog->time = level.time - level.startTime;
- Q_strncpyz( tklog->name, attacker->client->pers.netname, sizeof( tklog->name ) );
-
- if( victim )
- {
- Q_strncpyz( tklog->victim, victim->client->pers.netname, sizeof( tklog->victim ) );
- tklog->damage = victim->client->tkcredits[ attacker->s.number ];
- tklog->value = victim->client->ps.stats[ STAT_MAX_HEALTH ];
- }
- else
- {
- Q_strncpyz( tklog->victim, "^3BLEEDING", sizeof( tklog->victim ) );
- tklog->damage = attacker->client->pers.statscounters.spreebleeds;
- tklog->value = g_bleedingSpree.integer * 100;
- }
-
- tklog->team = attacker->client->ps.stats[ STAT_PTEAM ];
- if( meansOfDeath == MOD_GRENADE )
- tklog->weapon = WP_GRENADE;
- else if( tklog->team == PTE_HUMANS )
- tklog->weapon = attacker->s.weapon;
- else
- tklog->weapon = attacker->client->ps.stats[ STAT_PCLASS ];
-
- g_admin_tklog[ admin_tklog_index ] = tklog;
- admin_tklog_index++;
- if( admin_tklog_index >= MAX_ADMIN_TKLOGS )
- admin_tklog_index = 0;
-}
-
-qboolean G_admin_tklog( gentity_t *ent, int skiparg )
+void G_admin_cleanup( void )
{
- g_admin_tklog_t *results[ 10 ];
- int result_index = 0;
- char *search_name = NULL;
- int index;
- int skip = 0;
- int skipped = 0;
- int checked = 0;
- char n1[ MAX_NAME_LENGTH ];
- char fmt_name[ 16 ];
- char argbuf[ 32 ];
- char *weaponName;
- int name_length = 10;
- int max_id = 0;
- int i;
- qboolean match;
-
- memset( results, 0, sizeof( results ) );
-
- index = admin_tklog_index;
- for( i = 0; i < 10; i++ )
- {
- int prev;
-
- prev = index - 1;
- if( prev < 0 )
- prev = MAX_ADMIN_TKLOGS - 1;
- if( !g_admin_tklog[ prev ] )
- break;
- if( g_admin_tklog[ prev ]->id > max_id )
- max_id = g_admin_tklog[ prev ]->id;
- index = prev;
- }
-
- if( G_SayArgc() > 1 + skiparg )
- {
- G_SayArgv( 1 + skiparg, argbuf, sizeof( argbuf ) );
- if( ( *argbuf >= '0' && *argbuf <= '9' ) || *argbuf == '-' )
- {
- int id;
-
- id = atoi( argbuf );
- if( id < 0 )
- id += ( max_id - 9 );
- else if( id <= max_id - MAX_ADMIN_TKLOGS )
- id = max_id - MAX_ADMIN_TKLOGS + 1;
-
- if( id + 9 >= max_id )
- id = max_id - 9;
- if( id < 1 )
- id = 1;
- for( i = 0; i < MAX_ADMIN_TKLOGS; i++ )
- {
- if( g_admin_tklog[ i ]->id == id )
- {
- index = i;
- break;
- }
- }
- }
- else
- {
- search_name = argbuf;
- }
-
- if( G_SayArgc() > 2 + skiparg && ( search_name ) )
- {
- char skipbuf[ 4 ];
- G_SayArgv( 2 + skiparg, skipbuf, sizeof( skipbuf ) );
- skip = atoi( skipbuf );
- }
- }
+ g_admin_level_t *l;
+ g_admin_admin_t *a;
+ g_admin_ban_t *b;
+ g_admin_command_t *c;
+ void *n;
- if( search_name )
+ for( l = g_admin_levels; l; l = n )
{
- g_admin_tklog_t *result_swap[ 10 ];
-
- memset( &result_swap, 0, sizeof( result_swap ) );
-
- index = admin_tklog_index - 1;
- if( index < 0 )
- index = MAX_ADMIN_TKLOGS - 1;
-
- while( g_admin_tklog[ index ] &&
- checked < MAX_ADMIN_TKLOGS &&
- result_index < 10 )
- {
- match = qfalse;
-
- G_SanitiseString( g_admin_tklog[ index ]->name, n1, sizeof( n1 ) );
- if( strstr( n1, search_name ) )
- match = qtrue;
-
- if( match && skip > 0 )
- {
- match = qfalse;
- skip--;
- skipped++;
- }
- if( match )
- {
- result_swap[ result_index ] = g_admin_tklog[ index ];
- result_index++;
- }
-
- checked++;
- index--;
- if( index < 0 )
- index = MAX_ADMIN_TKLOGS - 1;
- }
- // search runs backwards, turn it around
- for( i = 0; i < result_index; i++ )
- results[ i ] = result_swap[ result_index - i - 1 ];
+ n = l->next;
+ BG_Free( l );
}
- else
+ g_admin_levels = NULL;
+ for( a = g_admin_admins; a; a = n )
{
- while( g_admin_tklog[ index ] && result_index < 10 )
- {
- results[ result_index ] = g_admin_tklog[ index ];
- result_index++;
- index++;
- if( index >= MAX_ADMIN_TKLOGS )
- index = 0;
- }
+ n = a->next;
+ BG_Free( a );
}
-
- for( i = 0; results[ i ] && i < 10; i++ )
- {
- int l;
-
- G_DecolorString( results[ i ]->name, n1 );
- l = strlen( n1 );
- if( l > name_length )
- name_length = l;
- }
- ADMBP_begin( );
- for( i = 0; results[ i ] && i < 10; i++ )
+ g_admin_admins = NULL;
+ for( b = g_admin_bans; b; b = n )
{
- int t;
-
- t = results[ i ]->time / 1000;
-
- G_DecolorString( results[ i ]->name, n1 );
- Com_sprintf( fmt_name, sizeof( fmt_name ), "%%%ds",
- ( name_length + (int)( strlen( results[ i ]->name ) - strlen( n1 ) ) ) );
- Com_sprintf( n1, sizeof( n1 ), fmt_name, results[ i ]->name );
-
- if( results[ i ]->team == PTE_HUMANS )
- weaponName = BG_FindNameForWeapon( results[ i ]->weapon );
- else
- weaponName = BG_FindNameForClassNum( results[ i ]->weapon );
-
- ADMBP( va( "^7%3d %3d:%02d %s^7 %3d / %3d %10s %s^7\n",
- results[ i ]->id,
- t / 60, t % 60,
- n1,
- results[ i ]->damage,
- results[ i ]->value,
- weaponName,
- results[ i ]->victim ) );
- }
- if( search_name )
- {
- ADMBP( va( "^3!tklog:^7 Showing %d matches for '%s^7'.",
- result_index,
- argbuf ) );
- if( checked < MAX_ADMIN_TKLOGS && g_admin_tklog[ checked ] )
- ADMBP( va( " run '!tklog %s^7 %d' to see more",
- argbuf,
- skipped + result_index ) );
- ADMBP( "\n" );
- }
- else if ( results[ 0 ] )
- {
- ADMBP( va( "^3!tklog:^7 Showing %d - %d of %d.\n",
- results[ 0 ]->id,
- results[ result_index - 1 ]->id,
- max_id ) );
+ n = b->next;
+ BG_Free( b );
}
- else
+ g_admin_bans = NULL;
+ for( c = g_admin_commands; c; c = n )
{
- ADMBP( "^3!tklog:^7 log is empty.\n" );
+ n = c->next;
+ BG_Free( c );
}
- ADMBP_end( );
-
- return qtrue;
+ g_admin_commands = NULL;
+ BG_DefragmentMemory( );
}
-qboolean G_admin_sm( gentity_t *ent, int skiparg )
+qboolean G_admin_sm( gentity_t *ent )
{
const char *s;
char feature[ 16 ];
- if( G_SayArgc() < 2 + skiparg )
+ if( trap_Argc() < 2 )
{
usage:
- ADMP( "^3!sm: ^7usage: !sm ipa <IPA>\n" );
+ ADMP( "^3sm: ^7usage: sm ipa <IPA>\n" );
return qfalse;
}
- s = G_SayConcatArgs( 1 + skiparg );
+ s = ConcatArgs( 1 );
if( strchr( s, '\n' ) || strchr( s, '\r' ) )
{
- ADMP( "^3!sm: ^7invalid character\n" );
+ ADMP( "^3sm: ^7invalid character\n" );
return qfalse;
}
- G_SayArgv( 1 + skiparg, feature, sizeof( feature ) );
+ trap_Argv( 1, feature, sizeof( feature ) );
if( !Q_stricmp( feature, "ipa" ) )
{
char ipa[ 32 ];
- int parts[ 4 ];
- if( G_SayArgc() > 3 + skiparg )
+ if( trap_Argc() > 3 )
{
- ADMP( "^3!sm: ^7excessive arguments\n" );
+ ADMP( "^3sm: ^7excessive arguments\n" );
goto usage;
}
- G_SayArgv( 2 + skiparg, ipa, sizeof( ipa ) );
-
- // have a well-formed IPv4 address, because Schachtmeister silently drops all invalid requests
-
- if( sscanf( ipa, "%i.%i.%i.%i", &parts[0], &parts[1], &parts[2], &parts[3] ) != 4
- || parts[0] < 0 || parts[0] > 255
- || parts[1] < 0 || parts[1] > 255
- || parts[2] < 0 || parts[2] > 255
- || parts[3] < 0 || parts[3] > 255 )
- {
- ADMP( "^3!sm: ^7invalid IP address\n" );
- return qfalse;
- }
-
- Com_sprintf( ipa, sizeof( ipa ), "%i.%i.%i.%i", parts[0], parts[1], parts[2], parts[3] );
+ trap_Argv( 2, ipa, sizeof( ipa ) );
if( rand() % 2 /* FIXME cache hit */ )
{
const char *answer = "interesting";
- ADMP( va( "^3!sm: ^7IP address %s is: %s\n", ipa, answer ) );
+ ADMP( va( "^3sm: ^7IP address '%s^7' is: %s\n", ipa, answer ) );
return qtrue;
}
- ADMP( "^3!sm: ^7hmm...\n" );
+ ADMP( "^3sm: ^7hmm...\n" );
trap_SendConsoleCommand( EXEC_APPEND, va( "smq ipa \"%s\"\n", ipa ) );
}
else
goto usage;
return qtrue;
-}
+} \ No newline at end of file