Valve Developer Community:Sandbox: Difference between revisions

From Valve Developer Community
Jump to navigation Jump to search
m (remember_the_names_2.sma)
m (remember_the_names_3.sma)
Line 1: Line 1:
<!-- Do not edit this line! -->{{sandbox}}<!-- Don't you dare! -->
<!-- Do not edit this line! -->{{sandbox}}<!-- Don't you dare! -->


#define PLUGINNAME "Remember the names"
#define PLUGINNAME "Remember the names"
 
#define VERSION "0.4.3"
#define VERSION "0.4.2"
#define AUTHOR "JGHG"
 
#define AUTHOR "JGHG"
 
/*
/*
Copyleft 2005
Copyleft 2005
Plugin topic: http://www.amxmodx.org/forums/viewtopic.php?p=92039
Plugin topic: http://www.amxmodx.org/forums/viewtopic.php?p=92039


PLUGINNAME
PLUGINNAME
==========
==========
Remembers names used by players.
Remembers names used by players.


In console you can type "amx_names <playername>" and you will have a list of the ten most common names ever used by that player.
In console you can type "amx_names <playername>" and you will have a list of the ten most common names ever used by that player.
The names are ordered by frequency and last time of use.
The names are ordered by frequency and last time of use.


When someone enters the server a welcome msg is displayed to all clients (or admins only depending on compile).
When someone enters the server a welcome msg is displayed to all clients (or admins only depending on compile).
If someone enters with a name less common than previously used names for that player,
If someone enters with a name less common than previously used names for that player,
the welcome msg will also contain up to three names most commonly used by the player.
the welcome msg will also contain up to three names most commonly used by the player.


Example: If I play 20 maps with the name "JGHG" and then 10 maps with "Johnny got his gun", and I enter another map
Example: If I play 20 maps with the name "JGHG" and then 10 maps with "Johnny got his gun", and I enter another map
with the name "Faken Icker" the welcome msg should look like "We welcome Faken Icker, aka: JGHG, Johnny got his gun".
with the name "Faken Icker" the welcome msg should look like "We welcome Faken Icker, aka: JGHG, Johnny got his gun".


Add these sql info cvars to sql.cfg:
Add these sql info cvars to sql.cfg:
rtn_host "127.0.0.1"
rtn_host "127.0.0.1"
rtn_user "myusername"
rtn_user "myusername"
rtn_pass "thesecretpassword"
rtn_pass "thesecretpassword"
 
rtn_db "thedb"
rtn_db "thedb"
 
 


You can replace ADMIN_CFG with whatever access level you want below. This access is a must to use "amx_names".
You can replace ADMIN_CFG with whatever access level you want below. This access is a must to use "amx_names".
*/
*/
 
#define ACCESS_AMXNAMES ADMIN_KICK // check amxconst.inc for the other access flags...
#define ACCESS_AMXNAMES ADMIN_KICK // check amxconst.inc for the other access flags...
 
/*
/*
You can also replace ADMIN_ADMIN below with whatever access level you want to be required to get the welcome msg about a user logging in...
You can also replace ADMIN_ADMIN below with whatever access level you want to be required to get the welcome msg about a user logging in...
*/
*/
 
#define ACCESS_WELCOMEMSG ADMIN_ALL  // you can replace ADMIN_CFG with ADMIN_ALL and everyone will receive the welcome msg
#define ACCESS_WELCOMEMSG ADMIN_KICK // you can replace ADMIN_CFG with ADMIN_ALL and everyone will receive the welcome msg
 
/*
/*
Note to SQLITE module users:
Note to SQLITE module users:
If you're using this module it doesn't matter what you write in ANY of the cvars BUT rtn_db, in fact that is the only cvar that will exist.
If you're using this module it doesn't matter what you write in ANY of the cvars BUT rtn_db, in fact that is the only cvar that will exist.
The rtn_db cvar should contain the full path to the db file from your top server directory, one step above the mod dir.
The rtn_db cvar should contain the full path to the db file from your top server directory, one step above the mod dir.
Ie if you set rtn_db to "cstrike/addons/amxmodx/data/rememberthenames.db" it will end up as that file in that directory.
Ie if you set rtn_db to "cstrike/addons/amxmodx/data/rememberthenames.db" it will end up as that file in that directory.


/JGHG
/JGHG




VERSIONS
VERSIONS
========
========
 
070519 0.4.3  Sun fixed some issues with displaying names.
070519 0.4.2 Fixed ' going straight to database engine
070211 0.4.2 Sir fixed some issues with displaying names.
 
050330 0.4.1       Attempt to work out bugs.
050330 0.4.1 Attempt to work out bugs.
050330 0.4 Fixed some issues with displaying names.
 
'amx_names' now displays the ten most common names used by specified player.
050330 0.4 Fixed some issues with displaying names.
You can now also define (at compile time) what access will be required to recieve the welcome msgs.
 
050113 0.3.1       Test version made to be compatible with Sqlite module. No new features.
'amx_names' now displays the ten most common names used by specified player.
050112 0.3 Prints a public welcome msg when someone enters.
 
If someone enters with a name less common than previously used names for that player,
You can now also define (at compile time) what access will be required to recieve the welcome msgs.
the welcome msg will also contain up to three names most commonly used by the player.
 
050111 0.2 Removed use of fakemeta, updated some stuff, fixed a real bug with displaying names... ingame names now display in a MOTD window.
050113 0.3.1 Test version made to be compatible with Sqlite module. No new features.
050110 0.1 First version
 
050112 0.3 Prints a public welcome msg when someone enters.
 
If someone enters with a name less common than previously used names for that player,
 
the welcome msg will also contain up to three names most commonly used by the player.
 
050111 0.2 Removed use of fakemeta, updated some stuff, fixed a real bug with displaying names... ingame names now display in a MOTD window.
 
050110 0.1 First version
 
 
 




CREDITS
CREDITS
=======
=======
Idea of Cryonic
Idea of Cryonic
*/
*/


#include <amxmodx>
#include <amxmodx>
#include <dbi>
#include <dbi>
#include <amxmisc>
#include <amxmisc>


 
#define CREATE_TABLE_STEAMIDS "CREATE TABLE IF NOT EXISTS steamids (steamid varchar(40) NOT NULL default '', id int(11) NOT NULL auto_increment, PRIMARY KEY (id), UNIQUE KEY STEAMID (steamid)) TYPE=MyISAM;"
 
#define CREATE_TABLE_NAMES "CREATE TABLE IF NOT EXISTS names ( timestamp int(10) unsigned NOT NULL default '0', counter int(10) unsigned NOT NULL default '1', id int(11) NOT NULL default '0', name varchar(32) binary NOT NULL default '', PRIMARY KEY (id,name)) TYPE=MyISAM; "
#define CREATE_TABLE_STEAMIDS "CREATE TABLE IF NOT EXISTS steamids (steamid varchar(40) NOT NULL default '', id int(11) NOT NULL auto_increment, PRIMARY KEY (id), UNIQUE KEY STEAMID (steamid)) TYPE=MyISAM;"
#define CREATE_TABLE_STEAMIDS_SQLITE "CREATE TABLE steamids (steamid VARCHAR NOT NULL DEFAULT '' UNIQUE, id INTEGER PRIMARY KEY)"
 
#define CREATE_TABLE_NAMES_SQLITE "CREATE TABLE names (timestamp INTEGER, counter INTEGER DEFAULT '1', id INTEGER, name VARCHAR BINARY NOT NULL DEFAULT '')"
#define CREATE_TABLE_NAMES "CREATE TABLE IF NOT EXISTS names ( timestamp int(10) unsigned NOT NULL default '0', counter int(10) unsigned NOT NULL default '1', id int(11) NOT NULL default '0', name varchar(32) binary NOT NULL default '', PRIMARY KEY (id,name)) TYPE=MyISAM; "
#define CVAR_HOST "rtn_host"
 
#define CVAR_USER "rtn_user"
#define CREATE_TABLE_STEAMIDS_SQLITE "CREATE TABLE steamids (steamid VARCHAR NOT NULL DEFAULT '' UNIQUE, id INTEGER PRIMARY KEY)"
#define CVAR_PASS "rtn_pass"
 
#define CVAR_DB "rtn_db"
#define CREATE_TABLE_NAMES_SQLITE "CREATE TABLE names (timestamp INTEGER, counter INTEGER DEFAULT '1', id INTEGER, name VARCHAR BINARY NOT NULL DEFAULT '')"
#define QSIZE 511
 
#define NROFCOMMONNAMES 3
#define CVAR_HOST "rtn_host"
#define CVAR_NOADMINS "rtn_noadmins"
 
#define CVAR_USER "rtn_user"
 
#define CVAR_PASS "rtn_pass"
 
#define CVAR_DB "rtn_db"
 
#define QSIZE 511
 
#define NROFCOMMONNAMES 3
 
#define CVAR_NOADMINS "rtn_noadmins"
 
 


// Globals below
// Globals below
new g_query[QSIZE + 1]
new g_query[QSIZE + 1]
 
new g_dbids[64] // stores the automatically generated id that is handled to each steamid by db
new g_dbids[33] // stores the automatically generated id that is handled to each steamid by db
new g_lastname[64][64]
 
new g_lastname[33][64]
 
new bool:g_sqlite
new bool:g_sqlite
 
new bool:g_inServer[64]
new bool:g_inServer[33]
 
// Globals above
// Globals above


stock admin_print(access, const DESTINATION, const MSG[]) {
stock admin_print(access, const DESTINATION, const MSG[]) {
new const MAXPLAYERS = get_maxplayers()


new const MAXPLAYERS = get_maxplayers()
new bool:mustBeAdmin
if (access & ADMIN_ADMIN) {
mustBeAdmin = true
access &= ~ADMIN_ADMIN
}
else
mustBeAdmin = false


for (new i = 1; i <= MAXPLAYERS; i++) {
// No offliners, bots or people without the required access.
if (!g_inServer[i] || !is_user_connected(i) || is_user_bot(i))
continue


if (mustBeAdmin && !is_user_admin(i))
continue


new bool:mustBeAdmin
if (access > 0 && !(get_user_flags(i) & access))
 
continue
if (access & ADMIN_ADMIN) {
 
mustBeAdmin = true
 
access &= ~ADMIN_ADMIN


client_print(i, DESTINATION, MSG)
}
}
}
else
mustBeAdmin = false
for (new i = 1; i <= MAXPLAYERS; i++) {
// No offliners, bots or people without the required access.
if (!g_inServer[i] || !is_user_connected(i) || is_user_bot(i))
continue
if (mustBeAdmin && !is_user_admin(i))
continue
if (access > 0 && !(get_user_flags(i) & access))
continue
client_print(i, DESTINATION, MSG)
}
}


public plugin_modules() {
public plugin_modules() {
 
require_module("dbi")
require_module("dbi")
 
}
}


public client_connect(id) {
public client_connect(id) {
 
g_lastname[id] = ""
g_lastname[id] = ""
g_dbids[id] = 0
 
g_inServer[id] = false
g_dbids[id] = 0
return PLUGIN_CONTINUE
 
g_inServer[id] = false
 
return PLUGIN_CONTINUE
 
}
}


public client_disconnect(id) {
public client_disconnect(id) {
 
g_inServer[id] = false
g_inServer[id] = false
return PLUGIN_CONTINUE
 
return PLUGIN_CONTINUE
 
}
}


jghg_free_result(Result:result) {
jghg_free_result(Result:result) {
 
if (result > RESULT_NONE) {
if (result > RESULT_NONE) {
//server_print("!!!REMOVE: %d", result)
 
dbi_free_result(result)
//server_print("!!!REMOVE: %d", result)
}
 
dbi_free_result(result)
 
}
 
}
}


public client_authorized(id) {
public client_authorized(id) {
if (is_user_bot(id))
return PLUGIN_CONTINUE


if (is_user_bot(id))
const LEN = 32
new steamid[LEN + 1], name[64]


return PLUGIN_CONTINUE
get_user_authid(id, steamid, LEN)
get_user_name(id, name, 31)


new Sql:sql
if (!connect(sql))
return PLUGIN_CONTINUE


if (!getdbidfromsteamid(id, steamid, false, sql)) {
format(g_query, QSIZE, "INSERT INTO steamids (steamid) VALUES ('%s')", steamid)
//server_print("client_authorized: sending query: %s", g_query)
new Result:result = dbi_query(sql, g_query)
jghg_free_result(result)


const LEN = 32
// Do this another time to get the dbid from database.
if (!getdbidfromsteamid(id, steamid, false, sql))
log_amx("Failed getting dbid for %s (%s)!", steamid, name)
}
//server_print("client_authorized: dbid for %d is %d", id, g_dbids[id])


new steamid[LEN + 1], name[64]
disconnect(sql)
 
 
 
get_user_authid(id, steamid, LEN)
 
get_user_name(id, name, 31)
 
 
 
new Sql:sql
 
if (!connect(sql))
 
return PLUGIN_CONTINUE
 
 
 
if (!getdbidfromsteamid(id, steamid, false, sql)) {
 
format(g_query, QSIZE, "INSERT INTO steamids (steamid) VALUES ('%s')", steamid)
 
//server_print("client_authorized: sending query: %s", g_query)
 
new Result:result = dbi_query(sql, g_query)
 
jghg_free_result(result)
 
 
 
// Do this another time to get the dbid from database.
 
if (!getdbidfromsteamid(id, steamid, false, sql))
 
log_amx("Failed getting dbid for %s (%s)!", steamid, name)


return PLUGIN_CONTINUE
}
}
//server_print("client_authorized: dbid for %d is %d", id, g_dbids[id])
disconnect(sql)
return PLUGIN_CONTINUE
}


bool:getdbidfromsteamid(id, steamid[], bool:doConnect, &Sql:sql = SQL_FAILED) {
bool:getdbidfromsteamid(id, steamid[], bool:doConnect, &Sql:sql = SQL_FAILED) {
g_dbids[id] = 0
new bool:exists = false
if (doConnect) {
if (!connect(sql))
return false
}
format(g_query, QSIZE, "SELECT id FROM steamids WHERE steamid = '%s' LIMIT 1", steamid)
//server_print("getdbidfromsteamid: Does query: %s", g_query)
new Result:result = dbi_query(sql, g_query)
//server_print("Query done, result: %d", result)
if (result < RESULT_OK && dbi_check_error(sql)) {
}
else if (dbi_nextrow(result)) {
g_dbids[id] = dbi_field(result, 1)
exists = true
}
jghg_free_result(result)
if (doConnect)
dbi_close(sql)


g_dbids[id] = 0
return exists
 
new bool:exists = false
 
if (doConnect) {
 
if (!connect(sql))
 
return false
 
}
 
format(g_query, QSIZE, "SELECT id FROM steamids WHERE steamid = '%s' LIMIT 1", steamid)
 
//server_print("getdbidfromsteamid: Does query: %s", g_query)
 
new Result:result = dbi_query(sql, g_query)
 
//server_print("Query done, result: %d", result)
 
if (result < RESULT_OK && dbi_check_error(sql)) {
 
}
}
else if (dbi_nextrow(result)) {
g_dbids[id] = dbi_field(result, 1)
exists = true
}
jghg_free_result(result)
if (doConnect)
dbi_close(sql)
return exists
}


name_to_db(id, name[], &Sql:sql = SQL_FAILED) {
name_to_db(id, name[], &Sql:sql = SQL_FAILED) {
if (g_dbids[id] == 0)
return


if (g_dbids[id] == 0)
new bool:disconnect_ = false
 
if (sql == SQL_FAILED) {
return
disconnect_ = true
 
if (!connect(sql))
 
return
 
}
new bool:disconnect_ = false
 
if (sql == SQL_FAILED) {
 
disconnect_ = true
 
if (!connect(sql))
 
return
 
}


replace_all(name,32,"'","''");


format(g_query, QSIZE, "SELECT counter FROM names WHERE id = '%d' AND name = '%s' LIMIT 1", g_dbids[id], name)


replace_all(name,64,"'","''");
//server_print("name_to_db: Sending query: %s", g_query)
new Result:result = dbi_query(sql, g_query)
//server_print("name_to_db: result=%d rows=%d", result, dbi_num_rows(result))
new const TIMESTAMP = get_systime()


if (result < RESULT_OK && dbi_check_error(sql)) {
// Error...
}
else if (dbi_nextrow(result)) {
// Record already in db. Increase counter
new counter = dbi_field(result, 1)
//server_print("NAME ALREADY MATCHES, INCREASING COUNTER from %d to %d", next, counter, counter + 1)
jghg_free_result(result)


counter++


format(g_query, QSIZE, "SELECT counter FROM names WHERE id = '%d' AND name = '%s' LIMIT 1", g_dbids[id], name)
if (g_sqlite)
format(g_query, QSIZE, "UPDATE names SET counter = %d, timestamp = %d WHERE id = %d AND name = '%s'", counter, TIMESTAMP, g_dbids[id], name)
else
format(g_query, QSIZE, "UPDATE names SET counter = %d, timestamp = %d WHERE id = %d AND name = '%s' LIMIT 1", counter, TIMESTAMP, g_dbids[id], name)
//server_print("name_to_db: Sending query: %s", g_query)
result = dbi_query(sql, g_query)
jghg_free_result(result)
//server_print("%s is already in db for %d (%d)", name, id, g_dbids[id])
}
else {
jghg_free_result(result)


format(g_query, QSIZE, "INSERT INTO names (id, name, timestamp) VALUES(%d, '%s', %d)", g_dbids[id], name, TIMESTAMP)
//server_print("name_to_db: Sending query: %s", g_query)
result = dbi_query(sql, g_query)
jghg_free_result(result)
}


 
if (disconnect_)
//server_print("name_to_db: Sending query: %s", g_query)
disconnect(sql)
 
new Result:result = dbi_query(sql, g_query)
 
//server_print("name_to_db: result=%d rows=%d", result, dbi_num_rows(result))
 
new const TIMESTAMP = get_systime()
 
 
 
if (result < RESULT_OK && dbi_check_error(sql)) {
 
// Error...
 
}
}
else if (dbi_nextrow(result)) {
// Record already in db. Increase counter
new counter = dbi_field(result, 1)
//server_print("NAME ALREADY MATCHES, INCREASING COUNTER from %d to %d", next, counter, counter + 1)
jghg_free_result(result)
counter++
if (g_sqlite)
format(g_query, QSIZE, "UPDATE names SET counter = %d, timestamp = %d WHERE id = %d AND name = '%s'", counter, TIMESTAMP, g_dbids[id], name)
else
format(g_query, QSIZE, "UPDATE names SET counter = %d, timestamp = %d WHERE id = %d AND name = '%s' LIMIT 1", counter, TIMESTAMP, g_dbids[id], name)
//server_print("name_to_db: Sending query: %s", g_query)
result = dbi_query(sql, g_query)
jghg_free_result(result)
//server_print("%s is already in db for %d (%d)", name, id, g_dbids[id])
}
else {
jghg_free_result(result)
format(g_query, QSIZE, "INSERT INTO names (id, name, timestamp) VALUES(%d, '%s', %d)", g_dbids[id], name, TIMESTAMP)
//server_print("name_to_db: Sending query: %s", g_query)
result = dbi_query(sql, g_query)
jghg_free_result(result)
}
if (disconnect_)
disconnect(sql)
}


bool:connect(&Sql:sql) {
bool:connect(&Sql:sql) {
const LEN = 128
new host[LEN], user[LEN], pass[LEN], db[LEN], error_msg[LEN]


const LEN = 128
if (!g_sqlite) {
get_cvar_string(CVAR_HOST, host, LEN - 1)
get_cvar_string(CVAR_USER, user, LEN - 1)
get_cvar_string(CVAR_PASS, pass, LEN - 1)
}
get_cvar_string(CVAR_DB, db, LEN - 1)


new host[LEN], user[LEN], pass[LEN], db[LEN], error_msg[LEN]
//server_print("Passing this to dbi_connect(%s, %s, %s, %s, %d)", host, user, pass, db, LEN - 1)


sql = dbi_connect(host, user, pass, db, error_msg, LEN - 1)
//server_print("dbi_connect = %d", sql)
if (sql < SQL_OK && dbi_check_error(sql)) {
log_amx("[%s] ERROR - Can't connect to SQL db: %s", PLUGINNAME, error_msg)


return false
}
else {
//log_amx("[%s] Successfully connected to SQL db.", PLUGINNAME)
//server_print("[%s] Successfully connected to SQL db.", PLUGINNAME)
}


if (!g_sqlite) {
return true
 
get_cvar_string(CVAR_HOST, host, LEN - 1)
 
get_cvar_string(CVAR_USER, user, LEN - 1)
 
get_cvar_string(CVAR_PASS, pass, LEN - 1)
 
}
}
get_cvar_string(CVAR_DB, db, LEN - 1)
//server_print("Passing this to dbi_connect(%s, %s, %s, %s, %d)", host, user, pass, db, LEN - 1)
sql = dbi_connect(host, user, pass, db, error_msg, LEN - 1)
//server_print("dbi_connect = %d", sql)
if (sql < SQL_OK && dbi_check_error(sql)) {
log_amx("[%s] ERROR - Can't connect to SQL db: %s", PLUGINNAME, error_msg)
return false
}
else {
//log_amx("[%s] Successfully connected to SQL db.", PLUGINNAME)
//server_print("[%s] Successfully connected to SQL db.", PLUGINNAME)
}
return true
}


dbi_check_error(&Sql:sql) {
dbi_check_error(&Sql:sql) {
new error[256] = ""
dbi_error(sql, error, 255)
if (error[0] && !equal(error, "Not an error")) {
log_amx("[%s] SQL error: %s", PLUGINNAME, error)


new error[256] = ""
return true
 
}
dbi_error(sql, error, 255)
 
if (error[0] && !equal(error, "Not an error")) {
 
log_amx("[%s] SQL error: %s", PLUGINNAME, error)
 
 
 
return true
 
}
 
 
 
return false


return false
}
}


disconnect(&Sql:sql) {
disconnect(&Sql:sql) {
 
if (sql > SQL_FAILED) {
if (sql > SQL_FAILED) {
dbi_close(sql)
 
sql = SQL_FAILED
dbi_close(sql)
}
 
sql = SQL_FAILED
 
}
 
}
}


public listnames(id, level, cid) {
public listnames(id, level, cid) {
if (!cmd_access(id, level, cid, 2))
return PLUGIN_HANDLED


if (!cmd_access(id, level, cid, 2))
new plname[64]
 
read_argv(1, plname, 32)
return PLUGIN_HANDLED
 
 
 
new plname[33]
 
read_argv(1, plname, 32)
 
 
 
new player = cmd_target(id, plname, 2) // 2 = allow yourself
 
if (!player)
 
return PLUGIN_HANDLED
 
else if (is_user_bot(player)) {
 
console_print(id, "[%s] Nahh, bots don't count.", PLUGINNAME)
 
return PLUGIN_HANDLED
 
}
 
 
 
const SIZE = 1023
 
new names[SIZE + 1]
 
getnames(id, player, names, SIZE)
 
 


new title[40]
new player = cmd_target(id, plname, 2) // 2 = allow yourself
if (!player)
return PLUGIN_HANDLED
else if (is_user_bot(player)) {
console_print(id, "[%s] Nahh, bots don't count.", PLUGINNAME)
return PLUGIN_HANDLED
}


get_user_authid(player, title, 39)
const SIZE = 1023
new names[SIZE + 1]
getnames(id, player, names, SIZE)


format(title, 39, "Names used by %s", title)
new title[40]
 
get_user_authid(player, title, 39)
if (id == 0) {
format(title, 39, "Names used by %s", title)
 
if (id == 0) {
console_print(id, title)
console_print(id, title)
 
console_print_byline(id, names)
console_print_byline(id, names)
}
else {
console_print(id, "Close the console to view the names as they are displayed in a MOTD window.")
show_motd(id, names, title)
}


return PLUGIN_HANDLED
}
}
else {
console_print(id, "Close the console to view the names as they are displayed in a MOTD window.")
show_motd(id, names, title)
}
return PLUGIN_HANDLED
}


console_print_byline(id, text[]) {
console_print_byline(id, text[]) {
new line[256], starti = 0
new const TEXTLENGTH = strlen(text)


new line[256], starti = 0
for (new i = 0; i < TEXTLENGTH; i++) {
 
if (text[i] != '^n')
new const TEXTLENGTH = strlen(text)
line[i - starti] = text[i] //linelen += format(line[linelen], 127 - linelen, "%c", text[i])
 
else {
 
line[i - starti] = 0
 
console_print(id, line)
for (new i = 0; i < TEXTLENGTH; i++) {
line[0] = 0
 
starti = i + 1
if (text[i] != '^n')
}
 
}
line[i - starti] = text[i] //linelen += format(line[linelen], 127 - linelen, "%c", text[i])
console_print(id, line)
 
else {
 
line[i - starti] = 0
 
console_print(id, line)
 
line[0] = 0
 
starti = i + 1
 
}
 
}
 
console_print(id, line)
 
}
}


getnames(id, player, nameshere[], const LEN) {
getnames(id, player, nameshere[], const LEN) {
if (g_dbids[player] == 0) {
format(nameshere, LEN, "Couldn't retrieve user's db id at login.")
return
}
new Sql:sql
connect(sql)


if (g_dbids[player] == 0) {
format(g_query, QSIZE, "SELECT name, counter, timestamp FROM names WHERE id = %d ORDER BY counter DESC, timestamp DESC LIMIT 10", g_dbids[player])
 
new Result:result = dbi_query(sql, g_query)
format(nameshere, LEN, "Couldn't retrieve user's db id at login.")
if (result < RESULT_OK && dbi_check_error(sql)) {
 
console_print(id, "[%s] Oops, db operation failed.", PLUGINNAME)
return
}
 
else {
}
new name[64], counter, timestamp, time_[64]
 
new len = 0
new Sql:sql
 
connect(sql)
 
 
 
format(g_query, QSIZE, "SELECT name, counter, timestamp FROM names WHERE id = %d ORDER BY counter DESC, timestamp DESC LIMIT 10", g_dbids[player])
 
new Result:result = dbi_query(sql, g_query)
 
if (result < RESULT_OK && dbi_check_error(sql)) {
 
console_print(id, "[%s] Oops, db operation failed.", PLUGINNAME)
 
}
 
else {
 
new name[64], counter, timestamp, time_[64]
 
new len = 0
 
 
 
if (id == 0) {
 
len = format(nameshere, LEN, "%31s%11s%20s^n", "Name", "Times used", "Last time used")
 
while (dbi_nextrow(result) && len < LEN) {
 
dbi_field(result, 1, name, 31)
 
counter = dbi_field(result, 2)
 
timestamp = dbi_field(result, 3)
 
format_time(time_, 31, "%y%m%d - %H:%M:%S", timestamp)
 
len += format(nameshere[len], LEN - len, "%31s%11d%20s^n", name, counter, time_)
 
}
 
//len += format(nameshere[len], LEN - len, "</table>", name)
 
}
 
else {
 
len = format(nameshere, LEN, "<table><tr><td><b>Name</b></td><td><b>Times used</b></td><td><b>Last time used</b></td></tr>")
 
while (dbi_nextrow(result) && len < LEN) {
 
dbi_field(result, 1, name, 31)
 
counter = dbi_field(result, 2)
 
timestamp = dbi_field(result, 3)
 
format_time(time_, 31, "%y%m%d - %H:%M:%S", timestamp)
 
len += format(nameshere[len], LEN - len, "<tr><td>%s</td><td>%d</td><td>%s</td></tr>", name, counter, time_)
 
}
 
len += format(nameshere[len], LEN - len, "</table>", name)
 
}
 


if (id == 0) {
len = format(nameshere, LEN, "%31s%11s%20s^n", "Name", "Times used", "Last time used")
while (dbi_nextrow(result) && len < LEN) {
dbi_field(result, 1, name, 31)
counter = dbi_field(result, 2)
timestamp = dbi_field(result, 3)
format_time(time_, 31, "%y%m%d - %H:%M:%S", timestamp)
len += format(nameshere[len], LEN - len, "%31s%11d%20s^n", name, counter, time_)
}
//len += format(nameshere[len], LEN - len, "</table>", name)
}
else {
len = format(nameshere, LEN, "<table><tr><td><b>Name</b></td><td><b>Times used</b></td><td><b>Last time used</b></td></tr>")
while (dbi_nextrow(result) && len < LEN) {
dbi_field(result, 1, name, 31)
counter = dbi_field(result, 2)
timestamp = dbi_field(result, 3)
format_time(time_, 31, "%y%m%d - %H:%M:%S", timestamp)
len += format(nameshere[len], LEN - len, "<tr><td>%s</td><td>%d</td><td>%s</td></tr>", name, counter, time_)
}
len += format(nameshere[len], LEN - len, "</table>", name)
}


jghg_free_result(result)
jghg_free_result(result)
}


disconnect(sql)
}
}
disconnect(sql)
}


public client_infochanged(id) {
public client_infochanged(id) {
if (is_user_bot(id) || g_dbids[id] == 0)
return PLUGIN_CONTINUE


if (is_user_bot(id) || g_dbids[id] == 0)
set_task(0.1, "checkname", id)
 
return PLUGIN_CONTINUE
 
 
 
set_task(0.1, "checkname", id)
 
 
 
return PLUGIN_CONTINUE


return PLUGIN_CONTINUE
}
}


public checkname(id) {
public checkname(id) {
if (!is_user_connected(id) || is_user_bot(id) || g_dbids[id] == 0)
return


if (!is_user_connected(id) || is_user_bot(id) || g_dbids[id] == 0)
new name[64]
 
get_user_name(id, name, 31)
return
if (!equal(name, g_lastname[id])) {
 
//client_print(id, print_chat, "your name changed, name: %s", name)
 
name_to_db(id, name)
 
new name[64]
 
get_user_name(id, name, 63)
 
if (!equal(name, g_lastname[id])) {
 
//client_print(id, print_chat, "your name changed, name: %s", name)
 
name_to_db(id, name)
 
 
 
g_lastname[id] = name
 
}


g_lastname[id] = name
}
}
}


/*stock bool:sqlite_table_exists(Sql:sql, table[]) {
/*stock bool:sqlite_table_exists(Sql:sql, table[]) {
new bool:exists
new query[128]
format(query, 127, "SELECT name FROM sqlite_master WHERE type='table' AND name='%s' LIMIT 1;", table)


new bool:exists
new Result:result = dbi_query(sql, query)
 
new query[128]
 
format(query, 127, "SELECT name FROM sqlite_master WHERE type='table' AND name='%s' LIMIT 1;", table)
 
 
 
new Result:result = dbi_query(sql, query)
 
 
 
if (dbi_nextrow(result))
 
exists = true
 
else
 
exists = false
 


if (dbi_nextrow(result))
exists = true
else
exists = false


if (result > RESULT_NONE)
if (result > RESULT_NONE)
 
dbi_free_result(result)
dbi_free_result(result)
 
 
 
return exists


return exists
}*/
}*/


bool:create_tables() {
bool:create_tables() {
new Sql:sql
if (!connect(sql)) {
log_amx("[%s] Failed connecting to database. Pausing plugin.", PLUGINNAME)
pause("a")
return false
}


new Sql:sql
new Result:result


if (!connect(sql)) {
if (!g_sqlite || (g_sqlite && !sqlite_table_exists(sql, "steamids"))) {
format(g_query, QSIZE, "%s", g_sqlite ? CREATE_TABLE_STEAMIDS_SQLITE : CREATE_TABLE_STEAMIDS)


log_amx("[%s] Failed connecting to database. Pausing plugin.", PLUGINNAME)
result = dbi_query(sql, g_query)


pause("a")
if (result <= RESULT_FAILED && dbi_check_error(sql)) {
log_amx("[%s] Error while creating steamid table. Pausing plugin.", PLUGINNAME)
disconnect(sql)
pause("a")
return false
}
jghg_free_result(result)
}


return false


}
if (!g_sqlite || (g_sqlite && !sqlite_table_exists(sql, "names"))) {
format(g_query, QSIZE, "%s", g_sqlite ? CREATE_TABLE_NAMES_SQLITE : CREATE_TABLE_NAMES)


result = dbi_query(sql, g_query)


if (result <= RESULT_FAILED && dbi_check_error(sql)) {
log_amx("[%s] Error while creating names table. Pausing plugin.", PLUGINNAME)
disconnect(sql)
pause("a")
return false
}
jghg_free_result(result)
}


new Result:result
disconnect(sql)
 
 
 
if (!g_sqlite || (g_sqlite && !sqlite_table_exists(sql, "steamids"))) {
 
format(g_query, QSIZE, "%s", g_sqlite ? CREATE_TABLE_STEAMIDS_SQLITE : CREATE_TABLE_STEAMIDS)
 
 
 
result = dbi_query(sql, g_query)
 
 
 
if (result <= RESULT_FAILED && dbi_check_error(sql)) {
 
log_amx("[%s] Error while creating steamid table. Pausing plugin.", PLUGINNAME)
 
disconnect(sql)
 
pause("a")
 
return false
 
}
 
jghg_free_result(result)


return true
}
}
if (!g_sqlite || (g_sqlite && !sqlite_table_exists(sql, "names"))) {
format(g_query, QSIZE, "%s", g_sqlite ? CREATE_TABLE_NAMES_SQLITE : CREATE_TABLE_NAMES)
result = dbi_query(sql, g_query)
if (result <= RESULT_FAILED && dbi_check_error(sql)) {
log_amx("[%s] Error while creating names table. Pausing plugin.", PLUGINNAME)
disconnect(sql)
pause("a")
return false
}
jghg_free_result(result)
}
disconnect(sql)
return true
}
/*
/*
stock jghg_is_user_admin(id, accessRequired = ADMIN_ADMIN) {
stock jghg_is_user_admin(id, accessRequired = ADMIN_ADMIN) {
 
return get_user_flags(id) & accessRequired
return get_user_flags(id) & accessRequired
 
}*/
}*/


public client_putinserver(id) {
public client_putinserver(id) {
g_inServer[id] = true
if (g_dbids[id] == 0 || is_user_bot(id) || (get_cvar_num(CVAR_NOADMINS) && is_user_admin(id))) {
return PLUGIN_CONTINUE
}


g_inServer[id] = true
set_task(10.0, "delayed_printcommonnames", id)
 
if (g_dbids[id] == 0 || is_user_bot(id) || (get_cvar_num(CVAR_NOADMINS) && is_user_admin(id))) {
 
return PLUGIN_CONTINUE
 
}
 
 
 
set_task(10.0, "delayed_printcommonnames", id)
 
 
 
return PLUGIN_CONTINUE


return PLUGIN_CONTINUE
}
}


public delayed_printcommonnames(id) {
public delayed_printcommonnames(id) {
if (!is_user_connected(id))
return
// Get three most common names from db.
new commonnames[NROFCOMMONNAMES][64]
new gotNames = get_common_names(commonnames, id)
new currentName[64]
get_user_name(id, currentName, 31)
if (gotNames == 1 || (gotNames > 1 && equal(currentName, commonnames[0]))) {
new msg[128]
format(msg, 127, "We welcome %s", currentName)
admin_print(ACCESS_WELCOMEMSG, print_chat, msg) //client_print(0, print_chat, "We welcome %s", currentName)
server_print(msg)
return
}


if (!is_user_connected(id))
new allNames[128], len = 0
 
for (new i = 0; i < gotNames && commonnames[i][0] != 0 && !equal(currentName, commonnames[i]); i++) {
return
len += format(allNames[len], 31 - len, "%s, ", commonnames[i])
 
//server_print("commonnames[%d] is %s", i, commonnames[i])
// Get three most common names from db.
}
 
xs_strtrim(allNames, 2, false)
new commonnames[NROFCOMMONNAMES][64]
 
new gotNames = get_common_names(commonnames, id)
 
new currentName[64]
 
get_user_name(id, currentName, 31)
 
if (gotNames == 1 || (gotNames > 1 && equal(currentName, commonnames[0]))) {
 
new msg[128]
 
format(msg, 127, "We welcome %s", currentName)
 
admin_print(ACCESS_WELCOMEMSG, print_chat, msg) //client_print(0, print_chat, "We welcome %s", currentName)
 
server_print(msg)
 
return


format(allNames, 127, "We welcome %s, aka: %s", currentName, allNames)
admin_print(ACCESS_WELCOMEMSG, print_chat, allNames) //client_print(0, print_chat, allNames)
server_print(allNames)
}
}
new allNames[128], len = 0
for (new i = 0; i < gotNames && commonnames[i][0] != 0 && !equal(currentName, commonnames[i]); i++) {
len += format(allNames[len], 31 - len, "%s, ", commonnames[i])
//server_print("commonnames[%d] is %s", i, commonnames[i])
}
xs_strtrim(allNames, 2, false)
format(allNames, 127, "We welcome %s, aka: %s", currentName, allNames)
admin_print(ACCESS_WELCOMEMSG, print_chat, allNames) //client_print(0, print_chat, allNames)
server_print(allNames)
}


// by JGHG, adapted
// by JGHG, adapted
// removes charstotrim number of charactes from stringtotrim's
// removes charstotrim number of charactes from stringtotrim's
 
// - beginning if fromleft is true
// - beginning if fromleft is true
// - end if fromleft is false
 
// - end if fromleft is false
 
// tested
// tested
stock xs_strtrim(stringtotrim[], charstotrim, bool:fromleft = true)
stock xs_strtrim(stringtotrim[], charstotrim, bool:fromleft = true)
{
if (charstotrim <= 0)
return;
if (fromleft)
{
{
if (charstotrim <= 0)
    return;


new maxlen = strlen(stringtotrim);
if (fromleft)
 
{
if (charstotrim > maxlen)
new maxlen = strlen(stringtotrim);
if (charstotrim > maxlen)
charstotrim = maxlen;


charstotrim = maxlen;
// In format, input and output regions can overlap
 
format(stringtotrim, maxlen, "%s", stringtotrim[charstotrim]);
 
}
 
else
// In format, input and output regions can overlap
{
 
new maxlen = strlen(stringtotrim) - charstotrim;
format(stringtotrim, maxlen, "%s", stringtotrim[charstotrim]);
if (maxlen < 0)
maxlen = 0;


// In format, input and output regions can overlap
format(stringtotrim, maxlen, "%s", stringtotrim);
}
}
}
else
{
new maxlen = strlen(stringtotrim) - charstotrim;
if (maxlen < 0)
maxlen = 0;
// In format, input and output regions can overlap
format(stringtotrim, maxlen, "%s", stringtotrim);
}
}


get_common_names(commonNames[NROFCOMMONNAMES][64], player) {
get_common_names(commonNames[NROFCOMMONNAMES][64], player) {
new namesCollected = 0
if (g_dbids[player] == 0) {
//format(nameshere, LEN, "Couldn't retrieve user's db id at login.")
return namesCollected
}
new Sql:sql
connect(sql)


new namesCollected = 0
format(g_query, QSIZE, "SELECT name FROM names WHERE id = %d ORDER BY counter DESC, timestamp DESC LIMIT %d", g_dbids[player], NROFCOMMONNAMES)
 
//server_print("get_common_names: Sending query: %s", g_query)
if (g_dbids[player] == 0) {
new Result:result = dbi_query(sql, g_query)
if (result < RESULT_OK && dbi_check_error(sql)) {
//console_print(id, "[%s] Oops, db operation failed.", PLUGINNAME)
disconnect(sql)
return namesCollected
}
//server_print("Done, rows gotten: %d", dbi_num_rows(result))


//format(nameshere, LEN, "Couldn't retrieve user's db id at login.")
for (new i = 0; dbi_nextrow(result) && i < NROFCOMMONNAMES; i++) {
dbi_field(result, 1, commonNames[i], 31)
namesCollected++
}


return namesCollected
jghg_free_result(result)
disconnect(sql)


return namesCollected
}
}
new Sql:sql
connect(sql)
format(g_query, QSIZE, "SELECT name FROM names WHERE id = %d ORDER BY counter DESC, timestamp DESC LIMIT %d", g_dbids[player], NROFCOMMONNAMES)
//server_print("get_common_names: Sending query: %s", g_query)
new Result:result = dbi_query(sql, g_query)
if (result < RESULT_OK && dbi_check_error(sql)) {
//console_print(id, "[%s] Oops, db operation failed.", PLUGINNAME)
disconnect(sql)
return namesCollected
}
//server_print("Done, rows gotten: %d", dbi_num_rows(result))
for (new i = 0; dbi_nextrow(result) && i < NROFCOMMONNAMES; i++) {
dbi_field(result, 1, commonNames[i], 31)
namesCollected++
}
jghg_free_result(result)
disconnect(sql)
return namesCollected
}


public plugin_init() {
public plugin_init() {
register_plugin(PLUGINNAME, VERSION, AUTHOR)


register_plugin(PLUGINNAME, VERSION, AUTHOR)
register_concmd("amx_names", "listnames", ACCESS_AMXNAMES, "<playername> - lists the ten most common names ever used by this player.")
 
 
 
register_concmd("amx_names", "listnames", ACCESS_AMXNAMES, "<playername> - lists the ten most common names ever used by this player.")
 
 
 
new dbitype[16]
 
dbi_type(dbitype, 15)
 
server_print("[%s] Using database type %s.", PLUGINNAME, dbitype)
 
if (equal(dbitype, "sqlite"))
 
g_sqlite = true
 
else
 
g_sqlite = false
 
 
 
if (!g_sqlite) {
 
register_cvar(CVAR_HOST, "127.0.0.1")
 
register_cvar(CVAR_USER, "")
 
register_cvar(CVAR_PASS, "")
 
}
 
register_cvar(CVAR_DB, "rememberthenames")
 
 
 
register_cvar(CVAR_NOADMINS, "0")
 
 
 
 
 
new sqlcfgpath[128]
 
get_configsdir(sqlcfgpath, 127)
 
format(sqlcfgpath, 127, "%s/sql.cfg", sqlcfgpath)
 
server_cmd("exec %s", sqlcfgpath)


server_exec() // To force execution of above cmd before progress? seems to do the trick...
new dbitype[16]
dbi_type(dbitype, 15)
server_print("[%s] Using database type %s.", PLUGINNAME, dbitype)
if (equal(dbitype, "sqlite"))
g_sqlite = true
else
g_sqlite = false


if (!g_sqlite) {
register_cvar(CVAR_HOST, "127.0.0.1")
register_cvar(CVAR_USER, "")
register_cvar(CVAR_PASS, "")
}
register_cvar(CVAR_DB, "rememberthenames")


register_cvar(CVAR_NOADMINS, "0")


if (create_tables())


server_print("[%s] Initialized successfully.", PLUGINNAME)
new sqlcfgpath[128]
get_configsdir(sqlcfgpath, 127)
format(sqlcfgpath, 127, "%s/sql.cfg", sqlcfgpath)
server_cmd("exec %s", sqlcfgpath)
server_exec() // To force execution of above cmd before progress? seems to do the trick...


if (create_tables())
server_print("[%s] Initialized successfully.", PLUGINNAME)
}
}

Revision as of 14:45, 28 November 2011

The Sandbox (Valve Developer Community:Sandbox) is a VDC namespace page designed for testing and experimenting with Wiki syntax. Feel free to try your skills at formatting here: click on edit, make your changes, and click 'Save page' when you are finished. Content added here will not stay permanently.

Please do not edit the "markup" text, at the top of the editing window, that reads "{{sandbox}}".


  1. define PLUGINNAME "Remember the names"
  2. define VERSION "0.4.3"
  3. define AUTHOR "JGHG"

/* Copyleft 2005 Plugin topic: http://www.amxmodx.org/forums/viewtopic.php?p=92039

PLUGINNAME

==

Remembers names used by players.

In console you can type "amx_names <playername>" and you will have a list of the ten most common names ever used by that player. The names are ordered by frequency and last time of use.

When someone enters the server a welcome msg is displayed to all clients (or admins only depending on compile). If someone enters with a name less common than previously used names for that player, the welcome msg will also contain up to three names most commonly used by the player.

Example: If I play 20 maps with the name "JGHG" and then 10 maps with "Johnny got his gun", and I enter another map with the name "Faken Icker" the welcome msg should look like "We welcome Faken Icker, aka: JGHG, Johnny got his gun".

Add these sql info cvars to sql.cfg: rtn_host "127.0.0.1" rtn_user "myusername" rtn_pass "thesecretpassword" rtn_db "thedb"

You can replace ADMIN_CFG with whatever access level you want below. This access is a must to use "amx_names".

  • /
  1. define ACCESS_AMXNAMES ADMIN_KICK // check amxconst.inc for the other access flags...

/* You can also replace ADMIN_ADMIN below with whatever access level you want to be required to get the welcome msg about a user logging in...

  • /
  1. define ACCESS_WELCOMEMSG ADMIN_ALL // you can replace ADMIN_CFG with ADMIN_ALL and everyone will receive the welcome msg

/* Note to SQLITE module users: If you're using this module it doesn't matter what you write in ANY of the cvars BUT rtn_db, in fact that is the only cvar that will exist. The rtn_db cvar should contain the full path to the db file from your top server directory, one step above the mod dir. Ie if you set rtn_db to "cstrike/addons/amxmodx/data/rememberthenames.db" it will end up as that file in that directory.

/JGHG


VERSIONS

==

070519 0.4.3 Sun fixed some issues with displaying names. 070211 0.4.2 Sir fixed some issues with displaying names. 050330 0.4.1 Attempt to work out bugs. 050330 0.4 Fixed some issues with displaying names. 'amx_names' now displays the ten most common names used by specified player. You can now also define (at compile time) what access will be required to recieve the welcome msgs. 050113 0.3.1 Test version made to be compatible with Sqlite module. No new features. 050112 0.3 Prints a public welcome msg when someone enters. If someone enters with a name less common than previously used names for that player, the welcome msg will also contain up to three names most commonly used by the player. 050111 0.2 Removed use of fakemeta, updated some stuff, fixed a real bug with displaying names... ingame names now display in a MOTD window. 050110 0.1 First version


CREDITS

=

Idea of Cryonic

  • /
  1. include <amxmodx>
  2. include <dbi>
  3. include <amxmisc>
  1. define CREATE_TABLE_STEAMIDS "CREATE TABLE IF NOT EXISTS steamids (steamid varchar(40) NOT NULL default , id int(11) NOT NULL auto_increment, PRIMARY KEY (id), UNIQUE KEY STEAMID (steamid)) TYPE=MyISAM;"
  2. define CREATE_TABLE_NAMES "CREATE TABLE IF NOT EXISTS names ( timestamp int(10) unsigned NOT NULL default '0', counter int(10) unsigned NOT NULL default '1', id int(11) NOT NULL default '0', name varchar(32) binary NOT NULL default , PRIMARY KEY (id,name)) TYPE=MyISAM; "
  3. define CREATE_TABLE_STEAMIDS_SQLITE "CREATE TABLE steamids (steamid VARCHAR NOT NULL DEFAULT UNIQUE, id INTEGER PRIMARY KEY)"
  4. define CREATE_TABLE_NAMES_SQLITE "CREATE TABLE names (timestamp INTEGER, counter INTEGER DEFAULT '1', id INTEGER, name VARCHAR BINARY NOT NULL DEFAULT )"
  5. define CVAR_HOST "rtn_host"
  6. define CVAR_USER "rtn_user"
  7. define CVAR_PASS "rtn_pass"
  8. define CVAR_DB "rtn_db"
  9. define QSIZE 511
  10. define NROFCOMMONNAMES 3
  11. define CVAR_NOADMINS "rtn_noadmins"

// Globals below new g_query[QSIZE + 1] new g_dbids[64] // stores the automatically generated id that is handled to each steamid by db new g_lastname[64][64] new bool:g_sqlite new bool:g_inServer[64] // Globals above

stock admin_print(access, const DESTINATION, const MSG[]) { new const MAXPLAYERS = get_maxplayers()

new bool:mustBeAdmin if (access & ADMIN_ADMIN) { mustBeAdmin = true access &= ~ADMIN_ADMIN } else mustBeAdmin = false

for (new i = 1; i <= MAXPLAYERS; i++) { // No offliners, bots or people without the required access. if (!g_inServer[i] || !is_user_connected(i) || is_user_bot(i)) continue

if (mustBeAdmin && !is_user_admin(i)) continue

if (access > 0 && !(get_user_flags(i) & access)) continue

client_print(i, DESTINATION, MSG) } }

public plugin_modules() { require_module("dbi") }

public client_connect(id) { g_lastname[id] = "" g_dbids[id] = 0 g_inServer[id] = false return PLUGIN_CONTINUE }

public client_disconnect(id) { g_inServer[id] = false return PLUGIN_CONTINUE }

jghg_free_result(Result:result) { if (result > RESULT_NONE) { //server_print("!!!REMOVE: %d", result) dbi_free_result(result) } }

public client_authorized(id) { if (is_user_bot(id)) return PLUGIN_CONTINUE

const LEN = 32 new steamid[LEN + 1], name[64]

get_user_authid(id, steamid, LEN) get_user_name(id, name, 31)

new Sql:sql if (!connect(sql)) return PLUGIN_CONTINUE

if (!getdbidfromsteamid(id, steamid, false, sql)) { format(g_query, QSIZE, "INSERT INTO steamids (steamid) VALUES ('%s')", steamid) //server_print("client_authorized: sending query: %s", g_query) new Result:result = dbi_query(sql, g_query) jghg_free_result(result)

// Do this another time to get the dbid from database. if (!getdbidfromsteamid(id, steamid, false, sql)) log_amx("Failed getting dbid for %s (%s)!", steamid, name) } //server_print("client_authorized: dbid for %d is %d", id, g_dbids[id])

disconnect(sql)

return PLUGIN_CONTINUE }

bool:getdbidfromsteamid(id, steamid[], bool:doConnect, &Sql:sql = SQL_FAILED) { g_dbids[id] = 0 new bool:exists = false if (doConnect) { if (!connect(sql)) return false } format(g_query, QSIZE, "SELECT id FROM steamids WHERE steamid = '%s' LIMIT 1", steamid) //server_print("getdbidfromsteamid: Does query: %s", g_query) new Result:result = dbi_query(sql, g_query) //server_print("Query done, result: %d", result) if (result < RESULT_OK && dbi_check_error(sql)) { } else if (dbi_nextrow(result)) { g_dbids[id] = dbi_field(result, 1) exists = true } jghg_free_result(result) if (doConnect) dbi_close(sql)

return exists }

name_to_db(id, name[], &Sql:sql = SQL_FAILED) { if (g_dbids[id] == 0) return

new bool:disconnect_ = false if (sql == SQL_FAILED) { disconnect_ = true if (!connect(sql)) return }

replace_all(name,32,"'","");

format(g_query, QSIZE, "SELECT counter FROM names WHERE id = '%d' AND name = '%s' LIMIT 1", g_dbids[id], name)

//server_print("name_to_db: Sending query: %s", g_query) new Result:result = dbi_query(sql, g_query) //server_print("name_to_db: result=%d rows=%d", result, dbi_num_rows(result)) new const TIMESTAMP = get_systime()

if (result < RESULT_OK && dbi_check_error(sql)) { // Error... } else if (dbi_nextrow(result)) { // Record already in db. Increase counter new counter = dbi_field(result, 1) //server_print("NAME ALREADY MATCHES, INCREASING COUNTER from %d to %d", next, counter, counter + 1) jghg_free_result(result)

counter++

if (g_sqlite) format(g_query, QSIZE, "UPDATE names SET counter = %d, timestamp = %d WHERE id = %d AND name = '%s'", counter, TIMESTAMP, g_dbids[id], name) else format(g_query, QSIZE, "UPDATE names SET counter = %d, timestamp = %d WHERE id = %d AND name = '%s' LIMIT 1", counter, TIMESTAMP, g_dbids[id], name) //server_print("name_to_db: Sending query: %s", g_query) result = dbi_query(sql, g_query) jghg_free_result(result) //server_print("%s is already in db for %d (%d)", name, id, g_dbids[id]) } else { jghg_free_result(result)

format(g_query, QSIZE, "INSERT INTO names (id, name, timestamp) VALUES(%d, '%s', %d)", g_dbids[id], name, TIMESTAMP) //server_print("name_to_db: Sending query: %s", g_query) result = dbi_query(sql, g_query) jghg_free_result(result) }

if (disconnect_) disconnect(sql) }

bool:connect(&Sql:sql) { const LEN = 128 new host[LEN], user[LEN], pass[LEN], db[LEN], error_msg[LEN]

if (!g_sqlite) { get_cvar_string(CVAR_HOST, host, LEN - 1) get_cvar_string(CVAR_USER, user, LEN - 1) get_cvar_string(CVAR_PASS, pass, LEN - 1) } get_cvar_string(CVAR_DB, db, LEN - 1)

//server_print("Passing this to dbi_connect(%s, %s, %s, %s, %d)", host, user, pass, db, LEN - 1)

sql = dbi_connect(host, user, pass, db, error_msg, LEN - 1) //server_print("dbi_connect = %d", sql) if (sql < SQL_OK && dbi_check_error(sql)) { log_amx("[%s] ERROR - Can't connect to SQL db: %s", PLUGINNAME, error_msg)

return false } else { //log_amx("[%s] Successfully connected to SQL db.", PLUGINNAME) //server_print("[%s] Successfully connected to SQL db.", PLUGINNAME) }

return true }

dbi_check_error(&Sql:sql) { new error[256] = "" dbi_error(sql, error, 255) if (error[0] && !equal(error, "Not an error")) { log_amx("[%s] SQL error: %s", PLUGINNAME, error)

return true }

return false }

disconnect(&Sql:sql) { if (sql > SQL_FAILED) { dbi_close(sql) sql = SQL_FAILED } }

public listnames(id, level, cid) { if (!cmd_access(id, level, cid, 2)) return PLUGIN_HANDLED

new plname[64] read_argv(1, plname, 32)

new player = cmd_target(id, plname, 2) // 2 = allow yourself if (!player) return PLUGIN_HANDLED else if (is_user_bot(player)) { console_print(id, "[%s] Nahh, bots don't count.", PLUGINNAME) return PLUGIN_HANDLED }

const SIZE = 1023 new names[SIZE + 1] getnames(id, player, names, SIZE)

new title[40] get_user_authid(player, title, 39) format(title, 39, "Names used by %s", title) if (id == 0) { console_print(id, title) console_print_byline(id, names) } else { console_print(id, "Close the console to view the names as they are displayed in a MOTD window.") show_motd(id, names, title) }

return PLUGIN_HANDLED }

console_print_byline(id, text[]) { new line[256], starti = 0 new const TEXTLENGTH = strlen(text)

for (new i = 0; i < TEXTLENGTH; i++) { if (text[i] != '^n') line[i - starti] = text[i] //linelen += format(line[linelen], 127 - linelen, "%c", text[i]) else { line[i - starti] = 0 console_print(id, line) line[0] = 0 starti = i + 1 } } console_print(id, line) }

getnames(id, player, nameshere[], const LEN) { if (g_dbids[player] == 0) { format(nameshere, LEN, "Couldn't retrieve user's db id at login.") return } new Sql:sql connect(sql)

format(g_query, QSIZE, "SELECT name, counter, timestamp FROM names WHERE id = %d ORDER BY counter DESC, timestamp DESC LIMIT 10", g_dbids[player]) new Result:result = dbi_query(sql, g_query) if (result < RESULT_OK && dbi_check_error(sql)) { console_print(id, "[%s] Oops, db operation failed.", PLUGINNAME) } else { new name[64], counter, timestamp, time_[64] new len = 0

if (id == 0) { len = format(nameshere, LEN, "%31s%11s%20s^n", "Name", "Times used", "Last time used") while (dbi_nextrow(result) && len < LEN) { dbi_field(result, 1, name, 31) counter = dbi_field(result, 2) timestamp = dbi_field(result, 3) format_time(time_, 31, "%y%m%d - %H:%M:%S", timestamp) len += format(nameshere[len], LEN - len, "%31s%11d%20s^n", name, counter, time_) }

//len += format(nameshere[len], LEN - len, "", name)

} else {

len = format(nameshere, LEN, "

")

while (dbi_nextrow(result) && len < LEN) { dbi_field(result, 1, name, 31) counter = dbi_field(result, 2) timestamp = dbi_field(result, 3) format_time(time_, 31, "%y%m%d - %H:%M:%S", timestamp)

len += format(nameshere[len], LEN - len, "", name, counter, time_)

}

len += format(nameshere[len], LEN - len, "
NameTimes usedLast time used
%s%d%s

", name)

}

jghg_free_result(result) }

disconnect(sql) }

public client_infochanged(id) { if (is_user_bot(id) || g_dbids[id] == 0) return PLUGIN_CONTINUE

set_task(0.1, "checkname", id)

return PLUGIN_CONTINUE }

public checkname(id) { if (!is_user_connected(id) || is_user_bot(id) || g_dbids[id] == 0) return

new name[64] get_user_name(id, name, 31) if (!equal(name, g_lastname[id])) { //client_print(id, print_chat, "your name changed, name: %s", name) name_to_db(id, name)

g_lastname[id] = name } }

/*stock bool:sqlite_table_exists(Sql:sql, table[]) { new bool:exists new query[128] format(query, 127, "SELECT name FROM sqlite_master WHERE type='table' AND name='%s' LIMIT 1;", table)

new Result:result = dbi_query(sql, query)

if (dbi_nextrow(result)) exists = true else exists = false

if (result > RESULT_NONE) dbi_free_result(result)

return exists }*/

bool:create_tables() { new Sql:sql if (!connect(sql)) { log_amx("[%s] Failed connecting to database. Pausing plugin.", PLUGINNAME) pause("a") return false }

new Result:result

if (!g_sqlite || (g_sqlite && !sqlite_table_exists(sql, "steamids"))) { format(g_query, QSIZE, "%s", g_sqlite ? CREATE_TABLE_STEAMIDS_SQLITE : CREATE_TABLE_STEAMIDS)

result = dbi_query(sql, g_query)

if (result <= RESULT_FAILED && dbi_check_error(sql)) { log_amx("[%s] Error while creating steamid table. Pausing plugin.", PLUGINNAME) disconnect(sql) pause("a") return false } jghg_free_result(result) }


if (!g_sqlite || (g_sqlite && !sqlite_table_exists(sql, "names"))) { format(g_query, QSIZE, "%s", g_sqlite ? CREATE_TABLE_NAMES_SQLITE : CREATE_TABLE_NAMES)

result = dbi_query(sql, g_query)

if (result <= RESULT_FAILED && dbi_check_error(sql)) { log_amx("[%s] Error while creating names table. Pausing plugin.", PLUGINNAME) disconnect(sql) pause("a") return false } jghg_free_result(result) }

disconnect(sql)

return true } /* stock jghg_is_user_admin(id, accessRequired = ADMIN_ADMIN) { return get_user_flags(id) & accessRequired }*/

public client_putinserver(id) { g_inServer[id] = true if (g_dbids[id] == 0 || is_user_bot(id) || (get_cvar_num(CVAR_NOADMINS) && is_user_admin(id))) { return PLUGIN_CONTINUE }

set_task(10.0, "delayed_printcommonnames", id)

return PLUGIN_CONTINUE }

public delayed_printcommonnames(id) { if (!is_user_connected(id)) return // Get three most common names from db. new commonnames[NROFCOMMONNAMES][64] new gotNames = get_common_names(commonnames, id) new currentName[64] get_user_name(id, currentName, 31) if (gotNames == 1 || (gotNames > 1 && equal(currentName, commonnames[0]))) { new msg[128] format(msg, 127, "We welcome %s", currentName) admin_print(ACCESS_WELCOMEMSG, print_chat, msg) //client_print(0, print_chat, "We welcome %s", currentName) server_print(msg) return }

new allNames[128], len = 0 for (new i = 0; i < gotNames && commonnames[i][0] != 0 && !equal(currentName, commonnames[i]); i++) { len += format(allNames[len], 31 - len, "%s, ", commonnames[i]) //server_print("commonnames[%d] is %s", i, commonnames[i]) } xs_strtrim(allNames, 2, false)

format(allNames, 127, "We welcome %s, aka: %s", currentName, allNames) admin_print(ACCESS_WELCOMEMSG, print_chat, allNames) //client_print(0, print_chat, allNames) server_print(allNames) }

// by JGHG, adapted // removes charstotrim number of charactes from stringtotrim's // - beginning if fromleft is true // - end if fromleft is false // tested stock xs_strtrim(stringtotrim[], charstotrim, bool:fromleft = true) { if (charstotrim <= 0)

   	return;

if (fromleft) { new maxlen = strlen(stringtotrim); if (charstotrim > maxlen) charstotrim = maxlen;

// In format, input and output regions can overlap format(stringtotrim, maxlen, "%s", stringtotrim[charstotrim]); } else { new maxlen = strlen(stringtotrim) - charstotrim; if (maxlen < 0) maxlen = 0;

// In format, input and output regions can overlap format(stringtotrim, maxlen, "%s", stringtotrim); } }

get_common_names(commonNames[NROFCOMMONNAMES][64], player) { new namesCollected = 0 if (g_dbids[player] == 0) { //format(nameshere, LEN, "Couldn't retrieve user's db id at login.") return namesCollected } new Sql:sql connect(sql)

format(g_query, QSIZE, "SELECT name FROM names WHERE id = %d ORDER BY counter DESC, timestamp DESC LIMIT %d", g_dbids[player], NROFCOMMONNAMES) //server_print("get_common_names: Sending query: %s", g_query) new Result:result = dbi_query(sql, g_query) if (result < RESULT_OK && dbi_check_error(sql)) { //console_print(id, "[%s] Oops, db operation failed.", PLUGINNAME) disconnect(sql) return namesCollected } //server_print("Done, rows gotten: %d", dbi_num_rows(result))

for (new i = 0; dbi_nextrow(result) && i < NROFCOMMONNAMES; i++) { dbi_field(result, 1, commonNames[i], 31) namesCollected++ }

jghg_free_result(result) disconnect(sql)

return namesCollected }

public plugin_init() { register_plugin(PLUGINNAME, VERSION, AUTHOR)

register_concmd("amx_names", "listnames", ACCESS_AMXNAMES, "<playername> - lists the ten most common names ever used by this player.")

new dbitype[16] dbi_type(dbitype, 15) server_print("[%s] Using database type %s.", PLUGINNAME, dbitype) if (equal(dbitype, "sqlite")) g_sqlite = true else g_sqlite = false

if (!g_sqlite) { register_cvar(CVAR_HOST, "127.0.0.1") register_cvar(CVAR_USER, "") register_cvar(CVAR_PASS, "") } register_cvar(CVAR_DB, "rememberthenames")

register_cvar(CVAR_NOADMINS, "0")


new sqlcfgpath[128] get_configsdir(sqlcfgpath, 127) format(sqlcfgpath, 127, "%s/sql.cfg", sqlcfgpath) server_cmd("exec %s", sqlcfgpath) server_exec() // To force execution of above cmd before progress? seems to do the trick...

if (create_tables()) server_print("[%s] Initialized successfully.", PLUGINNAME) }