08.03.2016, 01:54
pawn Код:
// ** INCLUDES
#include <a_samp>
// ** NATIVES
// *** WHIRLPOOL
native WP_Hash(buffer[], len, const str[]);
// ** DEFINES
// *** GENERAL
#define MAX_LOGIN_ATTEMPTS 3
// *** FUNCTIONS
#define isnull(%1) ((!(%1[0])) || (((%1[0]) == '\1') && (!(%1[1]))))
#define strcat_format(%0,%1,%2) format(%0[strlen(%0)], %1 - strlen(%0), %2)
// *** DIALOGS
#define DIALOG_REGISTER 0
#define DIALOG_CONFIRM_REGISTER 1
#define DIALOG_LOGIN 2
// *** PLAYER RESET TYPES
#define PLAYER_RESET_CONNECT 0
#define PLAYER_RESET_DISCONNECT 1
// *** DATABASE
// **** PATHS
#define DATABASE_PATH "database.db"
// **** TABLES
// ***** USERS
// ****** GENERAL
#define TABLE_USERS "USERS"
// ****** CONTENT
#define USER_SQL_ID "sql_id"
#define USER_NAME "name"
#define USER_PASSWORD "password"
#define USER_IP_ADDRESS "ip_address"
#define USER_SCORE "score"
#define USER_CASH "cash"
#define USER_ADMIN_LEVEL "admin_level"
// ** COLORS
// *** GENERAL
#define COLOR_WHITE 0xFFFFFFFF
#define COL_WHITE "{FFFFFF}"
#define COLOR_RED 0xFF0000FF
#define COL_RED "{FF0000}"
// *** CUSTOM
#define COLOR_ACCOUNT 0x37E9A0FF
#define COL_ACCOUNT "{37E9A0}"
// ** ARRAYS AND ENUMERATORS
enum eUserInfo
{
user_info_sql_id,
user_info_score,
user_info_cash,
user_info_admin_level
}
new aUserInfo[MAX_PLAYERS][eUserInfo];
// ** VARIABLES
// *** GLOBAL VARIABLES
// **** DATABASE
new DB:database;
// *** PER-PLAYER VARIABLES
// **** GENERAL
new pPasswordHash[MAX_PLAYERS][129],
pLoginAttempts[MAX_PLAYERS];
// **** PLAYER STATES
new bool:psSignedIn[MAX_PLAYERS] = false;
// ** HOOKS
stock Hook_SetPlayerScore(playerid, score)
{
aUserInfo[playerid][user_info_score] = score;
return SetPlayerScore(playerid, score);
}
#if defined _ALS_SetPlayerScore
#undef SetPlayerScore
#else
#define _ALS_SetPlayerScore
#endif
#define SetPlayerScore Hook_SetPlayerScore
// ** MAIN
main()
{
print("Loaded \"sqlite_login_system.amx\".");
}
// ** CALLBACKS
public OnGameModeInit()
{
LoadDatabase();
return 1;
}
public OnGameModeExit()
{
db_close(database);
return 1;
}
public OnPlayerConnect(playerid)
{
TogglePlayerSpectating(playerid, true);
ResetPlayerVariables(playerid, PLAYER_RESET_CONNECT);
new query[300], DBResult:result;
strcat(query, "SELECT `"#USER_SQL_ID"`");
strcat(query, " FROM `"#TABLE_USERS"`");
strcat_format(query, sizeof(query), " WHERE `"#USER_NAME"` = '%q' COLLATE NOCASE LIMIT 1", ReturnPlayerName(playerid));
result = db_query(database, query);
if(db_num_rows(result))
{
aUserInfo[playerid][user_info_sql_id] = db_get_field_assoc_int(result, USER_SQL_ID);
ShowLoginDialog(playerid);
}
else
{
ShowRegisterDialog(playerid);
}
db_free_result(result);
return 1;
}
public OnPlayerDisconnect(playerid, reason)
{
if(IsPlayerSignedIn(playerid))
{
new query[400];
strcat(query, "UPDATE `"#TABLE_USERS"` SET ");
strcat_format(query, sizeof(query), "`"#USER_SCORE"` = '%d',", aUserInfo[playerid][user_info_score]);
strcat_format(query, sizeof(query), "`"#USER_CASH"` = '%d',", aUserInfo[playerid][user_info_cash]);
strcat_format(query, sizeof(query), "`"#USER_ADMIN_LEVEL"` = '%d'", aUserInfo[playerid][user_info_admin_level]);
strcat_format(query, sizeof(query), " WHERE `"#USER_SQL_ID"` = '%d'", aUserInfo[playerid][user_info_sql_id]);
db_query(database, query);
}
ResetPlayerVariables(playerid, PLAYER_RESET_DISCONNECT);
return 1;
}
public OnDialogResponse(playerid, dialogid, response, listitem, inputtext[])
{
switch(dialogid)
{
case DIALOG_REGISTER:
{
if(!response)
{
KickPlayer(playerid);
}
else if(response)
{
if(isnull(inputtext))
{
ShowRegisterDialog(playerid);
}
else if(strlen(inputtext) < 3)
{
ShowRegisterDialog(playerid);
SendClientMessage(playerid, COLOR_RED, "Your password is too short, please try again.");
}
else if(strlen(inputtext) > 20)
{
ShowRegisterDialog(playerid);
SendClientMessage(playerid, COLOR_RED, "Your password is too long, please try again.");
}
else
{
WP_Hash(pPasswordHash[playerid], 129, inputtext);
ShowConfirmPasswordDialog(playerid);
}
}
}
case DIALOG_CONFIRM_REGISTER:
{
if(!response)
{
ShowRegisterDialog(playerid);
}
else if(response)
{
new hash[129];
WP_Hash(hash, sizeof(hash), inputtext);
if(isnull(inputtext))
{
ShowConfirmPasswordDialog(playerid);
}
else if(!strcmp(pPasswordHash[playerid], hash, true))
{
new name[MAX_PLAYER_NAME];
GetPlayerName(playerid, name, MAX_PLAYER_NAME);
new query_1[500];
strcat(query_1, "INSERT INTO `"#TABLE_USERS"` (");
strcat(query_1, "`"#USER_NAME"`,");
strcat(query_1, "`"#USER_PASSWORD"`,");
strcat(query_1, "`"#USER_IP_ADDRESS"`,");
strcat(query_1, "`"#USER_SCORE"`,");
strcat(query_1, "`"#USER_CASH"`,");
strcat(query_1, "`"#USER_ADMIN_LEVEL"`");
strcat(query_1, ") VALUES (");
strcat_format(query_1, sizeof(query_1), "'%q',", name); // USER_NAME
strcat_format(query_1, sizeof(query_1), "'%q',", hash); // USER_PASSWORD
strcat_format(query_1, sizeof(query_1), "'%q',", GetPlayerIP(playerid)); // USER_IP_ADDRESS
strcat(query_1, "'0',"); // USER_SCORE
strcat(query_1, "'0',"); // USER_CASH
strcat(query_1, "'0')"); // USER_ADMIN_LEVEL
db_query(database, query_1);
new query_2[300], DBResult:result;
strcat(query_2, "SELECT `"#USER_SQL_ID"`");
strcat(query_2, " FROM `"#TABLE_USERS"`");
strcat_format(query_2, sizeof(query_2), " WHERE `"#USER_NAME"` = '%q' COLLATE NOCASE LIMIT 1", name);
result = db_query(database, query_2);
aUserInfo[playerid][user_info_sql_id] = db_get_field_assoc_int(result, USER_SQL_ID);
db_free_result(result);
TogglePlayerSpectating(playerid, false);
psSignedIn[playerid] = true;
SendClientMessage(playerid, COLOR_ACCOUNT, "You have successfully registered your account.");
}
else
{
ShowConfirmPasswordDialog(playerid);
SendClientMessage(playerid, COLOR_RED, "That's not the same password as the first one.");
}
}
}
case DIALOG_LOGIN:
{
if(!response)
{
KickPlayer(playerid);
}
else if(response)
{
if(isnull(inputtext))
{
ShowLoginDialog(playerid);
}
else
{
new hash[129];
WP_Hash(hash, sizeof(hash), inputtext);
new query_1[500], DBResult:result;
strcat(query_1, "SELECT `"#USER_PASSWORD"`,");
strcat(query_1, "`"#USER_IP_ADDRESS"`,");
strcat(query_1, "`"#USER_SCORE"`,");
strcat(query_1, "`"#USER_CASH"`,");
strcat(query_1, "`"#USER_ADMIN_LEVEL"`");
strcat(query_1, " FROM `"#TABLE_USERS"`");
strcat(query_1, " WHERE `"#USER_SQL_ID"` = '%d' COLLATE NOCASE LIMIT 1", aUserInfo[playerid][user_info_sql_id]);
result = db_query(database, query_1);
if(db_num_rows(result))
{
new real_hash[129];
db_get_field_assoc(result, USER_PASSWORD, real_hash, sizeof(real_hash));
if(!isnull(real_hash) && !strcmp(real_hash, hash, true))
{
new ip_address[16], current_ip_address[16];
GetPlayerIp(playerid, ip_address, sizeof(ip_address));
db_get_field_assoc(result, USER_IP_ADDRESS, current_ip_address, sizeof(current_ip_address));
if(strcmp(ip_address, current_ip_address, true))
{
new query_2[128];
strcat(query_2, "UPDATE `"#TABLE_USERS"` SET ");
strcat_format(query_2, sizeof(query_2), "`"#USER_IP_ADDRESS"` = '%q'", ip_address);
strcat_format(query_2, sizeof(query_2), " WHERE `"#USER_SQL_ID"` = '%d'", aUserInfo[playerid][user_info_sql_id]);
db_query(database, query_2);
}
TogglePlayerSpectating(playerid, false);
SetPlayerScore(playerid, db_get_field_assoc_int(result, USER_SCORE));
SetPlayerMoney(playerid, db_get_field_assoc_int(result, USER_CASH));
aUserInfo[playerid][user_info_admin_level] = db_get_field_assoc_int(result, USER_ADMIN_LEVEL);
psSignedIn[playerid] = true;
SendClientMessage(playerid, COLOR_ACCOUNT, "You have successfully logged into your account.");
}
else
{
new string[144];
pLoginAttempts[playerid] ++;
format(string, sizeof(string), "Incorrect password. Attempts left: %d.", (MAX_LOGIN_ATTEMPTS - pLoginAttempts[playerid]));
SendClientMessage(playerid, COLOR_RED, string);
if(pLoginAttempts[playerid] == MAX_LOGIN_ATTEMPTS)
{
KickPlayer(playerid);
}
else
{
ShowLoginDialog(playerid);
}
}
}
db_free_result(result);
}
}
}
}
return 1;
}
// ** FUNCTIONS
// *** LOAD COMPONENTS
stock LoadDatabase()
{
database = db_open(DATABASE_PATH);
new query_1[400];
strcat(query_1, "CREATE TABLE IF NOT EXISTS `"#TABLE_USERS"` (");
strcat(query_1, "`"#USER_SQL_ID"` INTEGER PRIMARY KEY AUTOINCREMENT,");
strcat(query_1, "`"#USER_NAME"` TEXT,");
strcat(query_1, "`"#USER_PASSWORD"` TEXT,");
strcat(query_1, "`"#USER_IP_ADDRESS"` TEXT,");
strcat(query_1, "`"#USER_SCORE"` INTEGER,");
strcat(query_1, "`"#USER_CASH"` INTEGER,");
strcat(query_1, "`"#USER_ADMIN_LEVEL"` INTEGER)");
db_query(database, query_1);
return 1;
}
// *** LOAD PER-PLAYER VARIABLES
stock ResetPlayerVariables(playerid, reset_type)
{
switch(reset_type)
{
case PLAYER_RESET_CONNECT:
{
// ** ARRAYS AND ENUMERATORS
aUserInfo[playerid][user_info_sql_id] = 0;
aUserInfo[playerid][user_info_score] = 0;
aUserInfo[playerid][user_info_cash] = 0;
aUserInfo[playerid][user_info_admin_level] = 0;
}
case PLAYER_RESET_DISCONNECT:
{
// ** GENERAL
pLoginAttempts[playerid] = 0;
// ** PLAYER STATES
psSignedIn[playerid] = false;
}
}
return 1;
}
// *** GENERAL
stock GetPlayerIP(playerid)
{
new ip_address[16];
GetPlayerIp(playerid, ip_address, sizeof(ip_address));
return ip_address;
}
stock ShowRegisterDialog(playerid)
{
new string[256];
strcat_format(string, sizeof(string), "{FFFFFF}Welcome, %s!\n\n", ReturnPlayerName(playerid));
strcat(string, "You must register to play here.");
ShowPlayerDialog(playerid, DIALOG_REGISTER, DIALOG_STYLE_PASSWORD, "Register", string, "Next", "Close");
return 1;
}
stock ShowConfirmPasswordDialog(playerid)
{
new string[256];
strcat_format(string, sizeof(string), "{FFFFFF}Welcome, %s!\n\n", ReturnPlayerName(playerid));
strcat(string, "You must confirm your registration to play here.");
ShowPlayerDialog(playerid, DIALOG_CONFIRM_REGISTER, DIALOG_STYLE_PASSWORD, "Confirm Registration", string, "Register", "Back");
return 1;
}
stock ShowLoginDialog(playerid)
{
new string[256];
strcat_format(string, sizeof(string), "{FFFFFF}Welcome back, %s!\n\n", ReturnPlayerName(playerid));
strcat(string, "You must log into play here.");
ShowPlayerDialog(playerid, DIALOG_LOGIN, DIALOG_STYLE_PASSWORD, "Log In", string, "Log In", "Close");
return 1;
}
stock ReturnPlayerName(playerid)
{
new name[MAX_PLAYER_NAME];
GetPlayerName(playerid, name, MAX_PLAYER_NAME);
return name;
}
stock SetPlayerMoney(playerid, cash)
{
aUserInfo[playerid][user_info_cash] = cash;
ResetPlayerMoney(playerid);
return GivePlayerMoney(playerid, cash);
}
stock KickPlayer(playerid)
{
SetTimerEx("KickPlayerAction", 100, false, "i", playerid);
return 1;
}
forward KickPlayerAction(playerid);
public KickPlayerAction(playerid)
{
return Kick(playerid);
}
forward bool:IsPlayerSignedIn(playerid);
public bool:IsPlayerSignedIn(playerid)
{
return psSignedIn[playerid];
}