--- admincmd.sma 2007/11/16 15:12:40 16 +++ admincmd.sma 2007/11/16 15:29:57 17 @@ -35,26 +35,135 @@ #include #include -#define MAXRCONCVARS 16 +// This is not a dynamic array because it would be bad for 24/7 map servers. +#define OLD_CONNECTION_QUEUE 10 -new g_cvarRcon[MAXRCONCVARS][32] -new g_cvarRconNum new g_pauseCon new Float:g_pausAble new bool:g_Paused new bool:g_PauseAllowed = false new g_addCvar[] = "amx_cvar add %s" +new pausable; +new rcon_password; + +// Old connection queue +new g_Names[OLD_CONNECTION_QUEUE][32]; +new g_SteamIDs[OLD_CONNECTION_QUEUE][32]; +new g_IPs[OLD_CONNECTION_QUEUE][32]; +new g_Access[OLD_CONNECTION_QUEUE]; +new g_Tracker; +new g_Size; + +stock InsertInfo(id) +{ + + // Scan to see if this entry is the last entry in the list + // If it is, then update the name and access + // If it is not, then insert it again. + + if (g_Size > 0) + { + new ip[32] + new auth[32]; + + get_user_authid(id, auth, charsmax(auth)); + get_user_ip(id, ip, charsmax(ip), 1/*no port*/); + + new last = 0; + + if (g_Size < sizeof(g_SteamIDs)) + { + last = g_Size - 1; + } + else + { + last = g_Tracker - 1; + + if (last < 0) + { + last = g_Size - 1; + } + } + + if (equal(auth, g_SteamIDs[last]) && + equal(ip, g_IPs[last])) // need to check ip too, or all the nosteams will while it doesn't work with their illegitimate server + { + get_user_name(id, g_Names[last], charsmax(g_Names[])); + g_Access[last] = get_user_flags(id); + + return; + } + } + + // Need to insert the entry + + new target = 0; // the slot to save the info at + + // Queue is not yet full + if (g_Size < sizeof(g_SteamIDs)) + { + target = g_Size; + + ++g_Size; + + } + else + { + target = g_Tracker; + + ++g_Tracker; + // If we reached the end of the array, then move to the front + if (g_Tracker == sizeof(g_SteamIDs)) + { + g_Tracker = 0; + } + } + + get_user_authid(id, g_SteamIDs[target], charsmax(g_SteamIDs[])); + get_user_name(id, g_Names[target], charsmax(g_Names[])); + get_user_ip(id, g_IPs[target], charsmax(g_IPs[]), 1/*no port*/); + + g_Access[target] = get_user_flags(id); + +} +stock GetInfo(i, name[], namesize, auth[], authsize, ip[], ipsize, &access) +{ + if (i >= g_Size) + { + abort(AMX_ERR_NATIVE, "GetInfo: Out of bounds (%d:%d)", i, g_Size); + } + + new target = (g_Tracker + i) % sizeof(g_SteamIDs); + + copy(name, namesize, g_Names[target]); + copy(auth, authsize, g_SteamIDs[target]); + copy(ip, ipsize, g_IPs[target]); + access = g_Access[target]; + +} +public client_disconnect(id) +{ + if (!is_user_bot(id)) + { + InsertInfo(id); + } +} + public plugin_init() { register_plugin("Admin Commands", AMXX_VERSION_STR, "AMXX Dev Team") + register_dictionary("admincmd.txt") register_dictionary("common.txt") + register_dictionary("adminhelp.txt") + + register_concmd("amx_kick", "cmdKick", ADMIN_KICK, " [reason]") register_concmd("amx_ban", "cmdBan", ADMIN_BAN, " [reason]") register_concmd("amx_banip", "cmdBanIP", ADMIN_BAN, " [reason]") - register_concmd("amx_addban", "cmdAddBan", ADMIN_RCON, " [reason]") - register_concmd("amx_unban", "cmdUnban", ADMIN_BAN, "") + register_concmd("amx_addban", "cmdAddBan", ADMIN_BAN, "<^"authid^" or ip> [reason]") + register_concmd("amx_unban", "cmdUnban", ADMIN_BAN, "<^"authid^" or ip>") register_concmd("amx_slay", "cmdSlay", ADMIN_SLAY, "") register_concmd("amx_slap", "cmdSlap", ADMIN_SLAY, " [power]") register_concmd("amx_leave", "cmdLeave", ADMIN_KICK, " [tag] [tag] [tag]") @@ -66,9 +175,16 @@ register_concmd("amx_map", "cmdMap", ADMIN_MAP, "") register_concmd("amx_cfg", "cmdCfg", ADMIN_CFG, "") register_concmd("amx_nick", "cmdNick", ADMIN_SLAY, " ") + register_concmd("amx_last", "cmdLast", ADMIN_BAN, "- list the last few disconnected clients info"); register_clcmd("amx_rcon", "cmdRcon", ADMIN_RCON, "") register_clcmd("amx_showrcon", "cmdShowRcon", ADMIN_RCON, "") register_clcmd("pauseAck", "cmdLBack") + + + rcon_password=get_cvar_pointer("rcon_password"); + pausable=get_cvar_pointer("pausable"); + + } public plugin_cfg() @@ -82,6 +198,13 @@ server_cmd(g_addCvar, "amx_reserved_slots") server_cmd(g_addCvar, "amx_reservation") server_cmd(g_addCvar, "amx_conmotd_file") + server_cmd(g_addCvar, "amx_sql_table"); + server_cmd(g_addCvar, "amx_sql_host"); + server_cmd(g_addCvar, "amx_sql_user"); + server_cmd(g_addCvar, "amx_sql_pass"); + server_cmd(g_addCvar, "amx_sql_db"); + server_cmd(g_addCvar, "amx_sql_type"); + } public cmdKick(id, level, cid) @@ -91,7 +214,7 @@ new arg[32] read_argv(1, arg, 31) - new player = cmd_target(id, arg, 1) + new player = cmd_target(id, arg, CMDTARGET_OBEY_IMMUNITY | CMDTARGET_ALLOW_SELF) if (!player) return PLUGIN_HANDLED @@ -107,12 +230,8 @@ remove_quotes(reason) log_amx("Kick: ^"%s<%d><%s><>^" kick ^"%s<%d><%s><>^" (reason ^"%s^")", name, get_user_userid(id), authid, name2, userid2, authid2, reason) - - switch (get_cvar_num("amx_show_activity")) - { - case 2: client_print(0, print_chat, "%L", LANG_PLAYER, "ADMIN_KICK_2", name, name2) - case 1: client_print(0, print_chat, "%L", LANG_PLAYER, "ADMIN_KICK_1", name2) - } + + show_activity_key("ADMIN_KICK_1", "ADMIN_KICK_2", name, name2); if (is_user_bot(player)) server_cmd("kick #%d", userid2) @@ -148,12 +267,8 @@ } get_user_name(id, name, 31) - - switch (get_cvar_num("amx_show_activity")) - { - case 2: client_print(0, print_chat, "%L", LANG_PLAYER, "ADMIN_UNBAN_2", name, arg) - case 1: client_print(0, print_chat, "%L", LANG_PLAYER, "ADMIN_UNBAN_1", arg) - } + + show_activity_key("ADMIN_UNBAN_1", "ADMIN_UNBAN_2", name, arg); get_user_authid(id, authid, 31) log_amx("Cmd: ^"%s<%d><%s><>^" unban ^"%s^"", name, get_user_userid(id), authid, arg) @@ -161,10 +276,28 @@ return PLUGIN_HANDLED } +/* amx_addban is a special command now. + * If a user with rcon uses it, it bans the user. No questions asked. + * If a user without rcon but with ADMIN_BAN uses it, it will scan the old + * connection queue, and if it finds the info for a player in it, it will + * check their old access. If they have immunity, it will not ban. + * If they do not have immunity, it will ban. If the user is not found, + * it will refuse to ban the target. + */ + public cmdAddBan(id, level, cid) { - if (!cmd_access(id, level, cid, 3)) - return PLUGIN_HANDLED + if (!cmd_access(id, level, cid, 3, true)) // check for ADMIN_BAN access + { + if (get_user_flags(id) & level) // Getting here means they didn't input enough args + { + return PLUGIN_HANDLED; + } + if (!cmd_access(id, ADMIN_RCON, cid, 3)) // If somehow they have ADMIN_RCON without ADMIN_BAN, continue + { + return PLUGIN_HANDLED; + } + } new arg[32], authid[32], name[32], minutes[32], reason[32] @@ -172,6 +305,87 @@ read_argv(2, minutes, 31) read_argv(3, reason, 31) + + if (!(get_user_flags(id) & ADMIN_RCON)) + { + new bool:canban = false; + new bool:isip = false; + // Limited access to this command + if (equali(arg, "STEAM_ID_PENDING") || + equali(arg, "STEAM_ID_LAN") || + equali(arg, "HLTV") || + equali(arg, "4294967295") || + equali(arg, "VALVE_ID_LAN") || + equali(arg, "VALVE_ID_PENDING")) + { + // Hopefully we never get here, so ML shouldn't be needed + console_print(id, "Cannot ban %s", arg); + return PLUGIN_HANDLED; + } + + if (contain(arg, ".") != -1) + { + isip = true; + } + + // Scan the disconnection queue + if (isip) + { + new IP[32]; + new Name[32]; + new dummy[1]; + new Access; + for (new i = 0; i < g_Size; i++) + { + GetInfo(i, Name, charsmax(Name), dummy, 0, IP, charsmax(IP), Access); + + if (equal(IP, arg)) + { + if (Access & ADMIN_IMMUNITY) + { + console_print(id, "[AMXX] %s : %L", IP, id, "CLIENT_IMM", Name); + + return PLUGIN_HANDLED; + } + // User did not have immunity + canban = true; + } + } + } + else + { + new Auth[32]; + new Name[32]; + new dummy[1]; + new Access; + for (new i = 0; i < g_Size; i++) + { + GetInfo(i, Name, charsmax(Name), Auth, charsmax(Auth), dummy, 0, Access); + + if (equal(Auth, arg)) + { + if (Access & ADMIN_IMMUNITY) + { + console_print(id, "[AMXX] %s : %L", Auth, id, "CLIENT_IMM", Name); + + return PLUGIN_HANDLED; + } + // User did not have immunity + canban = true; + } + } + } + + if (!canban) + { + console_print(id, "[AMXX] You may only ban recently disconnected clients. Use ^"amx_last^" to view."); + + return PLUGIN_HANDLED; + } + + } + + // User has access to ban their target if (contain(arg, ".") != -1) { server_cmd("addip ^"%s^" ^"%s^";wait;writeip", minutes, arg) @@ -183,11 +397,7 @@ get_user_name(id, name, 31) - switch (get_cvar_num("amx_show_activity")) - { - case 2: client_print(0, print_chat, "%L", LANG_PLAYER, "ADMIN_ADDBAN_2", name, arg) - case 1: client_print(0, print_chat, "%L", LANG_PLAYER, "ADMIN_ADDBAN_1", arg) - } + show_activity_key("ADMIN_ADDBAN_1", "ADMIN_ADDBAN_2", name, arg); get_user_authid(id, authid, 31) log_amx("Cmd: ^"%s<%d><%s><>^" ban ^"%s^" (minutes ^"%s^") (reason ^"%s^")", name, get_user_userid(id), authid, arg, minutes, reason) @@ -206,7 +416,7 @@ read_argv(2, minutes, 7) read_argv(3, reason, 63) - new player = cmd_target(id, target, 9) + new player = cmd_target(id, target, CMDTARGET_OBEY_IMMUNITY | CMDTARGET_NO_BOTS | CMDTARGET_ALLOW_SELF) if (!player) return PLUGIN_HANDLED @@ -234,32 +444,34 @@ else server_cmd("kick #%d ^"%s %s^";wait;banid ^"%s^" ^"%s^";wait;writeid", userid2, banned, temp, minutes, authid2) - new activity = get_cvar_num("amx_show_activity") - if (activity != 0) + + // Display the message to all clients + + new msg[256]; + new len; + new maxpl = get_maxplayers(); + for (new i = 1; i <= maxpl; i++) { - new players[32], pnum, msg[256], len - get_players(players, pnum, "c") - - for (new i = 0; i < pnum; i++) + if (is_user_connected(i) && !is_user_bot(i)) { - len = format(msg, 255, "%L", players[i], "ADMIN") - - if (activity == 1) - len += copy(msg[len], 255-len, ":") - else - len += format(msg[len], 255-len, " %s:", name) - - len += format(msg[len], 255-len, " %L", players[i], "BAN") - len += format(msg[len], 255-len, " %s ", name2) - + len = formatex(msg, charsmax(msg), "%L", i, "BAN"); + len += formatex(msg[len], charsmax(msg) - len, " %s ", name2); if (nNum) - format(msg[len], 255-len, "%L", players[i], "FOR_MIN", minutes) + { + formatex(msg[len], charsmax(msg) - len, "%L", i, "FOR_MIN", minutes); + } else - format(msg[len], 255-len, "%L", players[i], "PERM") - - client_print(players[i], print_chat, "%s", msg) + { + formatex(msg[len], charsmax(msg) - len, "%L", i, "PERM"); + } + if (strlen(reason) > 0) + { + formatex(msg[len], charsmax(msg) - len, " (%L: %s)", i, "REASON", reason); + } + show_activity_id(i, id, name, msg); } } + console_print(id, "[AMXX] %L", id, "CLIENT_BANNED", name2) return PLUGIN_HANDLED @@ -276,10 +488,14 @@ read_argv(2, minutes, 7) read_argv(3, reason, 63) - new player = cmd_target(id, target, 9) + new player = cmd_target(id, target, CMDTARGET_OBEY_IMMUNITY | CMDTARGET_NO_BOTS | CMDTARGET_ALLOW_SELF) if (!player) + { + // why is this here? + player = cmd_target(id, target, 9); return PLUGIN_HANDLED + } new authid[32], name2[32], authid2[32], name[32] new userid2 = get_user_userid(player) @@ -306,32 +522,33 @@ else server_cmd("kick #%d ^"%s %s^";wait;addip ^"%s^" ^"%s^";wait;writeip", userid2, banned, temp, minutes, address) - new activity = get_cvar_num("amx_show_activity") - if (activity != 0) + // Display the message to all clients + + new msg[256]; + new len; + new maxpl = get_maxplayers(); + for (new i = 1; i <= maxpl; i++) { - new players[32], pnum, msg[256], len - get_players(players, pnum, "c") - - for (new i = 0; i < pnum; i++) + if (is_user_connected(i) && !is_user_bot(i)) { - len = format(msg, 255, "%L", players[i], "ADMIN") - - if (activity == 1) - len += copy(msg[len], 255-len, ":") - else - len += format(msg[len], 255-len, " %s:", name) - - len += format(msg[len], 255-len, " %L", players[i], "BAN") - len += format(msg[len], 255-len, " %s ", name2) - + len = formatex(msg, charsmax(msg), "%L", i, "BAN"); + len += formatex(msg[len], charsmax(msg) - len, " %s ", name2); if (nNum) - format(msg[len], 255-len, "%L", players[i], "FOR_MIN", minutes) + { + formatex(msg[len], charsmax(msg) - len, "%L", i, "FOR_MIN", minutes); + } else - format(msg[len], 255-len, "%L", players[i], "PERM") - - client_print(players[i], print_chat, "%s", msg) + { + formatex(msg[len], charsmax(msg) - len, "%L", i, "PERM"); + } + if (strlen(reason) > 0) + { + formatex(msg[len], charsmax(msg) - len, " (%L: %s)", i, "REASON", reason); + } + show_activity_id(i, id, name, msg); } } + console_print(id, "[AMXX] %L", id, "CLIENT_BANNED", name2) return PLUGIN_HANDLED @@ -346,7 +563,7 @@ read_argv(1, arg, 31) - new player = cmd_target(id, arg, 5) + new player = cmd_target(id, arg, CMDTARGET_OBEY_IMMUNITY | CMDTARGET_ALLOW_SELF | CMDTARGET_ONLY_ALIVE) if (!player) return PLUGIN_HANDLED @@ -362,11 +579,8 @@ log_amx("Cmd: ^"%s<%d><%s><>^" slay ^"%s<%d><%s><>^"", name, get_user_userid(id), authid, name2, get_user_userid(player), authid2) - switch (get_cvar_num("amx_show_activity")) - { - case 2: client_print(0, print_chat, "%L", LANG_PLAYER, "ADMIN_SLAY_2", name, name2) - case 1: client_print(0, print_chat, "%L", LANG_PLAYER, "ADMIN_SLAY_1", name2) - } + show_activity_key("ADMIN_SLAY_1", "ADMIN_SLAY_2", name, name2); + console_print(id, "[AMXX] %L", id, "CLIENT_SLAYED", name2) return PLUGIN_HANDLED @@ -380,7 +594,7 @@ new arg[32] read_argv(1, arg, 31) - new player = cmd_target(id, arg, 5) + new player = cmd_target(id, arg, CMDTARGET_OBEY_IMMUNITY | CMDTARGET_ALLOW_SELF | CMDTARGET_ONLY_ALIVE) if (!player) return PLUGIN_HANDLED @@ -400,11 +614,8 @@ log_amx("Cmd: ^"%s<%d><%s><>^" slap with %d damage ^"%s<%d><%s><>^"", name, get_user_userid(id), authid, damage, name2, get_user_userid(player), authid2) - switch (get_cvar_num("amx_show_activity")) - { - case 2: client_print(0, print_chat, "%L", LANG_PLAYER, "ADMIN_SLAP_2", name, name2, damage) - case 1: client_print(0, print_chat, "%L", LANG_PLAYER, "ADMIN_SLAP_1", name2, damage) - } + show_activity_key("ADMIN_SLAP_1", "ADMIN_SLAP_2", name, name2, damage); + console_print(id, "[AMXX] %L", id, "CLIENT_SLAPED", name2, damage) return PLUGIN_HANDLED @@ -434,11 +645,7 @@ get_user_authid(id, authid, 31) get_user_name(id, name, 31) - switch (get_cvar_num("amx_show_activity")) - { - case 2: client_print(0, print_chat, "%L", LANG_PLAYER, "ADMIN_MAP_2", name, arg) - case 1: client_print(0, print_chat, "%L", LANG_PLAYER, "ADMIN_MAP_1", arg) - } + show_activity_key("ADMIN_MAP_1", "ADMIN_MAP_2", name, arg); log_amx("Cmd: ^"%s<%d><%s><>^" changelevel ^"%s^"", name, get_user_userid(id), authid, arg) @@ -456,12 +663,14 @@ return PLUGIN_HANDLED } -onlyRcon(name[]) +stock bool:onlyRcon(const name[]) { - for (new a = 0; a < g_cvarRconNum; ++a) - if (equali(g_cvarRcon[a], name)) - return 1 - return 0 + new ptr=get_cvar_pointer(name); + if (ptr && get_pcvar_flags(ptr) & FCVAR_PROTECTED) + { + return true; + } + return false; } public cmdCvar(id, level, cid) @@ -474,19 +683,23 @@ read_argv(1, arg, 31) read_argv(2, arg2, 63) + new pointer; + if (equal(arg, "add") && (get_user_flags(id) & ADMIN_RCON)) { - if (cvar_exists(arg2)) + if ((pointer=get_cvar_pointer(arg2))!=0) { - if (g_cvarRconNum < MAXRCONCVARS) - copy(g_cvarRcon[g_cvarRconNum++], 31, arg2) - else - console_print(id, "[AMXX] %L", id, "NO_MORE_CVARS") + new flags=get_pcvar_flags(pointer); + + if (!(flags & FCVAR_PROTECTED)) + { + set_pcvar_flags(pointer,flags | FCVAR_PROTECTED); + } } return PLUGIN_HANDLED } - if (!cvar_exists(arg)) + if ((pointer=get_cvar_pointer(arg))==0) { console_print(id, "[AMXX] %L", id, "UNKNOWN_CVAR", arg) return PLUGIN_HANDLED @@ -494,18 +707,18 @@ if (onlyRcon(arg) && !(get_user_flags(id) & ADMIN_RCON)) { - console_print(id, "[AMXX] %L", id, "CVAR_NO_ACC") - return PLUGIN_HANDLED - } - else if (equal(arg, "sv_password") && !(get_user_flags(id) & ADMIN_PASSWORD)) - { - console_print(id, "[AMXX] %L", id, "CVAR_NO_ACC") - return PLUGIN_HANDLED + // Exception for the new onlyRcon rules: + // sv_password is allowed to be modified by ADMIN_PASSWORD + if (!(equali(arg,"sv_password") && (get_user_flags(id) & ADMIN_PASSWORD))) + { + console_print(id, "[AMXX] %L", id, "CVAR_NO_ACC") + return PLUGIN_HANDLED + } } if (read_argc() < 3) { - get_cvar_string(arg, arg2, 63) + get_pcvar_string(pointer, arg2, 63) console_print(id, "[AMXX] %L", id, "CVAR_IS", arg, arg2) return PLUGIN_HANDLED } @@ -517,30 +730,28 @@ log_amx("Cmd: ^"%s<%d><%s><>^" set cvar (name ^"%s^") (value ^"%s^")", name, get_user_userid(id), authid, arg, arg2) set_cvar_string(arg, arg2) + + + // Display the message to all clients - new activity = get_cvar_num("amx_show_activity") - if (activity != 0) + new cvar_val[64]; + new maxpl = get_maxplayers(); + for (new i = 1; i <= maxpl; i++) { - new players[32], pnum, admin[64], cvar_val[64], len - get_players(players, pnum, "c") - - for (new i = 0; i < pnum; i++) + if (is_user_connected(i) && !is_user_bot(i)) { - len = format(admin, 255, "%L", players[i], "ADMIN") - - if (activity == 1) - len += copy(admin[len], 255-len, ":") - else - len += format(admin[len], 255-len, " %s:", name) - - if (equal(arg, "rcon_password") || equal(arg, "sv_password")) - format(cvar_val, 63, "*** %L ***", players[i], "PROTECTED") + if (get_pcvar_flags(pointer) & FCVAR_PROTECTED || equali(arg, "rcon_password")) + { + formatex(cvar_val, charsmax(cvar_val), "*** %L ***", i, "PROTECTED"); + } else - copy(cvar_val, 63, arg2) - - client_print(players[i], print_chat, "%L", players[i], "SET_CVAR_TO", admin, arg, arg2) + { + copy(cvar_val, charsmax(cvar_val), arg2); + } + show_activity_id(i, id, name, "%L", i, "SET_CVAR_TO", "", arg, cvar_val); } } + console_print(id, "[AMXX] %L", id, "CVAR_CHANGED", arg, arg2) return PLUGIN_HANDLED @@ -550,6 +761,13 @@ { if (!cmd_access(id, level, cid, 1)) return PLUGIN_HANDLED + + if (id==0) // If server executes redirect this to "amxx plugins" for more in depth output + { + server_cmd("amxx plugins"); + server_exec(); + return PLUGIN_HANDLED; + } new name[32], version[32], author[32], filename[32], status[32] new lName[32], lVersion[32], lAuthor[32], lFile[32], lStatus[32] @@ -560,21 +778,50 @@ format(lFile, 31, "%L", id, "FILE") format(lStatus, 31, "%L", id, "STATUS") + new StartPLID=0; + new EndPLID; + + new Temp[96] + new num = get_pluginsnum() + + if (read_argc() > 1) + { + read_argv(1,Temp,sizeof(Temp)-1); + StartPLID=str_to_num(Temp)-1; // zero-based + } + + EndPLID=min(StartPLID + 10, num); + new running = 0 - console_print(id, "%L:", id, "LOADED_PLUGINS") - console_print(id, "%-18.17s %-8.7s %-17.16s %-16.15s %-9.8s", lName, lVersion, lAuthor, lFile, lStatus) + console_print(id, "----- %L -----", id, "LOADED_PLUGINS") + console_print(id, "%-18.17s %-11.10s %-17.16s %-16.15s %-9.8s", lName, lVersion, lAuthor, lFile, lStatus) - for (new i = 0; i <%s><>^" leave some group (tag1 ^"%s^") (tag2 ^"%s^") (tag3 ^"%s^") (tag4 ^"%s^")", name, get_user_userid(id), authid, ltags[0], ltags[1], ltags[2], ltags[3]) - switch(get_cvar_num("amx_show_activity")) - { - case 2: client_print(0, print_chat, "%L", LANG_PLAYER, "ADMIN_LEAVE_2", name, ltags[0], ltags[1], ltags[2], ltags[3]) - case 1: client_print(0, print_chat, "%L", LANG_PLAYER, "ADMIN_LEAVE_1", ltags[0], ltags[1], ltags[2], ltags[3]) - } + show_activity_key("ADMIN_LEAVE_1", "ADMIN_LEAVE_2", name, ltags[0], ltags[1], ltags[2], ltags[3]); return PLUGIN_HANDLED } @@ -881,7 +1122,7 @@ read_argv(1, arg1, 31) read_argv(2, arg2, 31) - new player = cmd_target(id, arg1, 1) + new player = cmd_target(id, arg1, CMDTARGET_OBEY_IMMUNITY | CMDTARGET_ALLOW_SELF) if (!player) return PLUGIN_HANDLED @@ -895,12 +1136,42 @@ log_amx("Cmd: ^"%s<%d><%s><>^" change nick to ^"%s^" ^"%s<%d><%s><>^"", name, get_user_userid(id), authid, arg2, name2, get_user_userid(player), authid2) - switch (get_cvar_num("amx_show_activity")) - { - case 2: client_print(0, print_chat, "%L", LANG_PLAYER, "ADMIN_NICK_2", name, name2, arg2) - case 1: client_print(0, print_chat, "%L", LANG_PLAYER, "ADMIN_NICK_1", name2, arg2) - } + show_activity_key("ADMIN_NICK_1", "ADMIN_NICK_2", name, name2, arg2); + console_print(id, "[AMXX] %L", id, "CHANGED_NICK", name2, arg2) return PLUGIN_HANDLED } + +public cmdLast(id, level, cid) +{ + if (!cmd_access(id, level, cid, 1)) + { + return PLUGIN_HANDLED; + } + + new name[32]; + new authid[32]; + new ip[32]; + new flags[32]; + new access; + + + // This alignment is a bit weird (it should grow if the name is larger) + // but otherwise for the more common shorter name, it'll wrap in server console + // Steam client display is all skewed anyway because of the non fixed font. + console_print(id, "%19s %20s %15s %s", "name", "authid", "ip", "access"); + + for (new i = 0; i < g_Size; i++) + { + GetInfo(i, name, charsmax(name), authid, charsmax(authid), ip, charsmax(ip), access); + + get_flags(access, flags, charsmax(flags)); + + console_print(id, "%19s %20s %15s %s", name, authid, ip, flags); + } + + console_print(id, "%d old connections saved.", g_Size); + + return PLUGIN_HANDLED; +}