Valve Developer Community:Sandbox: Difference between revisions

From Valve Developer Community
Jump to navigation Jump to search
m (remember_the_names_1.sma)
m (remember_the_names_2.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.1"
 
#define AUTHOR "JGHG"
#define VERSION "0.4.2"
 
#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_CFG // 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_CFG // 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
========
========
050330 0.4.1 Attempt to work out bugs.
 
050330 0.4 Fixed some issues with displaying names.
070519 0.4.2 Fixed ' going straight to database engine
'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.
050330 0.4.1 Attempt to work out bugs.
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.
050330 0.4 Fixed some issues with displaying names.
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.
'amx_names' now displays the ten most common names used by specified 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
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
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_SQLITE "CREATE TABLE steamids (steamid VARCHAR NOT NULL DEFAULT '' UNIQUE, id INTEGER PRIMARY KEY)"
#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_SQLITE "CREATE TABLE names (timestamp INTEGER, counter INTEGER DEFAULT '1', id INTEGER, name VARCHAR BINARY NOT NULL DEFAULT '')"
 
#define CVAR_HOST "rtn_host"
#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_USER "rtn_user"
 
#define CVAR_PASS "rtn_pass"
#define CREATE_TABLE_STEAMIDS_SQLITE "CREATE TABLE steamids (steamid VARCHAR NOT NULL DEFAULT '' UNIQUE, id INTEGER PRIMARY KEY)"
#define CVAR_DB "rtn_db"
 
#define QSIZE 511
#define CREATE_TABLE_NAMES_SQLITE "CREATE TABLE names (timestamp INTEGER, counter INTEGER DEFAULT '1', id INTEGER, name VARCHAR BINARY NOT NULL DEFAULT '')"
#define NROFCOMMONNAMES 3
 
#define CVAR_NOADMINS "rtn_noadmins"
#define CVAR_HOST "rtn_host"
 
#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[33] // 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[33][32]
 
new g_lastname[33][64]
 
new bool:g_sqlite
new bool:g_sqlite
new bool:g_inServer[33]
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 bool:mustBeAdmin
new const MAXPLAYERS = get_maxplayers()
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))
new bool:mustBeAdmin
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_dbids[id] = 0
g_lastname[id] = ""
g_inServer[id] = false
 
return PLUGIN_CONTINUE
g_dbids[id] = 0
 
g_inServer[id] = false
 
return PLUGIN_CONTINUE
 
}
}


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


jghg_free_result(Result:result) {
jghg_free_result(Result:result) {
if (result > RESULT_NONE) {
 
//server_print("!!!REMOVE: %d", result)
if (result > RESULT_NONE) {
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


const LEN = 32
if (is_user_bot(id))
new steamid[LEN + 1], name[32]
 
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)
 
}


get_user_authid(id, steamid, LEN)
//server_print("client_authorized: dbid for %d is %d", id, g_dbids[id])
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.
disconnect(sql)
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
 
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)


return exists
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) {
name_to_db(id, name[], &Sql:sql = SQL_FAILED) {
if (g_dbids[id] == 0)
return


new bool:disconnect_ = false
if (g_dbids[id] == 0)
if (sql == SQL_FAILED) {
 
disconnect_ = true
return
if (!connect(sql))
 
return
 
}
 
new bool:disconnect_ = false
 
if (sql == SQL_FAILED) {
 
disconnect_ = true
 
if (!connect(sql))
 
return
 
}
 
 
 
replace_all(name,64,"'","''");
 
 
 
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, "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++
format(g_query, QSIZE, "INSERT INTO names (id, name, timestamp) VALUES(%d, '%s', %d)", g_dbids[id], name, TIMESTAMP)


if (g_sqlite)
//server_print("name_to_db: Sending query: %s", g_query)
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)
result = dbi_query(sql, g_query)
//server_print("name_to_db: Sending query: %s", g_query)
 
result = dbi_query(sql, g_query)
jghg_free_result(result)
jghg_free_result(result)
}


if (disconnect_)
disconnect(sql)
}
}
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]


if (!g_sqlite) {
const LEN = 128
get_cvar_string(CVAR_HOST, host, LEN - 1)
 
get_cvar_string(CVAR_USER, user, LEN - 1)
new host[LEN], user[LEN], pass[LEN], db[LEN], error_msg[LEN]
get_cvar_string(CVAR_PASS, pass, LEN - 1)
 
}
 
get_cvar_string(CVAR_DB, db, LEN - 1)
 
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)
 
}


//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
return true
}
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)


return true
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
}
}
return false
}


disconnect(&Sql:sql) {
disconnect(&Sql:sql) {
if (sql > SQL_FAILED) {
 
dbi_close(sql)
if (sql > SQL_FAILED) {
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


new plname[33]
if (!cmd_access(id, level, cid, 2))
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 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 title[40]
new names[SIZE + 1]
getnames(id, player, names, SIZE)


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


for (new i = 0; i < TEXTLENGTH; i++) {
new line[256], starti = 0
if (text[i] != '^n')
 
line[i - starti] = text[i] //linelen += format(line[linelen], 127 - linelen, "%c", text[i])
new const TEXTLENGTH = strlen(text)
else {
 
line[i - starti] = 0
 
console_print(id, line)
 
line[0] = 0
for (new i = 0; i < TEXTLENGTH; i++) {
starti = i + 1
 
}
if (text[i] != '^n')
}
 
console_print(id, line)
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) {
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])
if (g_dbids[player] == 0) {
new Result:result = dbi_query(sql, g_query)
 
if (result < RESULT_OK && dbi_check_error(sql)) {
format(nameshere, LEN, "Couldn't retrieve user's db id at login.")
console_print(id, "[%s] Oops, db operation failed.", PLUGINNAME)
 
}
return
else {
 
new name[32], counter, timestamp, time_[32]
}
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


set_task(0.1, "checkname", id)
if (is_user_bot(id) || g_dbids[id] == 0)
 
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


new name[32]
if (!is_user_connected(id) || is_user_bot(id) || g_dbids[id] == 0)
get_user_name(id, name, 31)
 
if (!equal(name, g_lastname[id])) {
return
//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 Result:result = dbi_query(sql, query)
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 (dbi_nextrow(result))
exists = true
else
exists = false


if (result > RESULT_NONE)
dbi_free_result(result)


return exists
if (result > RESULT_NONE)
 
dbi_free_result(result)
 
 
 
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 Result:result
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)


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)) {
result = dbi_query(sql, g_query)
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)) {


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


disconnect(sql)
disconnect(sql)
 
pause("a")
 
return false


return true
}
}
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
}


set_task(10.0, "delayed_printcommonnames", 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


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][32]
new gotNames = get_common_names(commonnames, id)
new currentName[32]
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
if (!is_user_connected(id))
for (new i = 0; i < gotNames && commonnames[i][0] != 0 && !equal(currentName, commonnames[i]); i++) {
 
len += format(allNames[len], 31 - len, "%s, ", commonnames[i])
return
//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
 
// - end if fromleft is false
// - beginning if fromleft is true
 
// - 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)
{
new maxlen = strlen(stringtotrim);
if (charstotrim > maxlen)
charstotrim = maxlen;
// In format, input and output regions can overlap
format(stringtotrim, maxlen, "%s", stringtotrim[charstotrim]);
}
else
{
{
if (charstotrim <= 0)
    return;


if (fromleft)
new maxlen = strlen(stringtotrim) - charstotrim;
{
 
new maxlen = strlen(stringtotrim);
if (maxlen < 0)
if (charstotrim > maxlen)
 
charstotrim = maxlen;
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)


// In format, input and output regions can overlap
namesCollected++
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][32], 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++) {
jghg_free_result(result)
dbi_field(result, 1, commonNames[i], 31)
namesCollected++
}


jghg_free_result(result)
disconnect(sql)
disconnect(sql)
 
 
 
return namesCollected


return namesCollected
}
}


public plugin_init() {
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.")
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)


new dbitype[16]
server_exec() // To force execution of above cmd before progress? seems to do the trick...
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())


new sqlcfgpath[128]
server_print("[%s] Initialized successfully.", PLUGINNAME)
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:44, 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"
  1. define VERSION "0.4.2"
  1. 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_KICK // 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.2 Fixed ' going straight to database engine

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>
  1. include <dbi>
  1. 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;"
  1. 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; "
  1. define CREATE_TABLE_STEAMIDS_SQLITE "CREATE TABLE steamids (steamid VARCHAR NOT NULL DEFAULT UNIQUE, id INTEGER PRIMARY KEY)"
  1. define CREATE_TABLE_NAMES_SQLITE "CREATE TABLE names (timestamp INTEGER, counter INTEGER DEFAULT '1', id INTEGER, name VARCHAR BINARY NOT NULL DEFAULT )"
  1. define CVAR_HOST "rtn_host"
  1. define CVAR_USER "rtn_user"
  1. define CVAR_PASS "rtn_pass"
  1. define CVAR_DB "rtn_db"
  1. define QSIZE 511
  1. define NROFCOMMONNAMES 3
  1. define CVAR_NOADMINS "rtn_noadmins"


// Globals below

new g_query[QSIZE + 1]

new g_dbids[33] // stores the automatically generated id that is handled to each steamid by db

new g_lastname[33][64]

new bool:g_sqlite

new bool:g_inServer[33]

// 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,64,"'","");


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[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]

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, 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

}

}


/*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)

}